diff --git a/README.md b/README.md index 37c73be..47ad579 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,15 @@ -# gamin-python3 +# Gamin, Python 3 migration -Gamin (File Alteration Monitor) - Python 3 migration \ No newline at end of file +> Gamin (File Alteration Monitor) - Python 3 migration + +[A patch](code/patch_python3.patch) in this repository adds Python 3 support for [Gamin File Alteration Monitor](https://people.gnome.org/~veillard/gamin/) and migrates from Python 2 to Python 3. It is necessary in modern environments using Gamin software. + +Other patch files are hosted on [AUR - Gamin](https://aur.archlinux.org/packages/gamin/). + +Gamin source code archive is provided as backup, as well. It can be found on [official Gamin website](https://people.gnome.org/~veillard/gamin/downloads.html). + +Necessary files are in `code` subfolder. + +## License + +[LGPL3](LICENSE), same as used by Gamin. diff --git a/code/0001-Poll-files-on-nfs4.patch b/code/0001-Poll-files-on-nfs4.patch new file mode 100644 index 0000000..f776732 --- /dev/null +++ b/code/0001-Poll-files-on-nfs4.patch @@ -0,0 +1,27 @@ +From b92b17ecced6df463da73d6de566740cf5cd00d4 Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Fri, 1 Feb 2013 15:19:58 +0100 +Subject: [PATCH 1/2] Poll files on nfs4 + +Add nfs4 among polled filesystems. + +https://bugzilla.gnome.org/show_bug.cgi?id=693006 +--- + server/gam_fs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/server/gam_fs.c b/server/gam_fs.c +index c8ca704..143a603 100644 +--- a/server/gam_fs.c ++++ b/server/gam_fs.c +@@ -178,6 +178,7 @@ gam_fs_init (void) + gam_fs_set ("reiserfs", GFS_MT_DEFAULT, 0); + gam_fs_set ("novfs", GFS_MT_POLL, 30); + gam_fs_set ("nfs", GFS_MT_POLL, 5); ++ gam_fs_set ("nfs4", GFS_MT_POLL, 5); + if (stat("/etc/mtab", &mtab_sbuf) != 0) + { + GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/mtab\n"); +-- +1.8.1.2 + diff --git a/code/18_gam_server_deadlocks.patch b/code/18_gam_server_deadlocks.patch new file mode 100644 index 0000000..ef77496 --- /dev/null +++ b/code/18_gam_server_deadlocks.patch @@ -0,0 +1,70 @@ +From cc14440eface093548cb3bc7814da11d9a99d283 Mon Sep 17 00:00:00 2001 +From: Anssi Hannula +Date: Wed, 4 Jan 2012 00:23:55 +0200 +Subject: [PATCH] fix possible server deadlock in ih_sub_cancel + +ih_sub_foreach() calls ih_sub_cancel() while inotify_lock is locked. +However, ih_sub_cancel() locks it again, and locking GMutex recursively +causes undefined behaviour. + +Fix that by removing locking from ih_sub_cancel() as ih_sub_foreach() +is its only user. Also make the function static so that it won't +accidentally get used by other files without locking (inotify-helper.h +is an internal server header). + +This should fix the intermittent deadlocks I've been experiencing +causing KDE applications to no longer start, and probably also +http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=542361 + +Origin: http://bugzilla-attachments.gnome.org/attachment.cgi?id=204537 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gamin/+bug/926862 +Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=542361 + +--- + server/inotify-helper.c | 7 ++----- + server/inotify-helper.h | 1 - + 2 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/server/inotify-helper.c b/server/inotify-helper.c +index d77203e..0789fa4 100644 +--- a/server/inotify-helper.c ++++ b/server/inotify-helper.c +@@ -123,13 +123,11 @@ ih_sub_add (ih_sub_t * sub) + + /** + * Cancels a subscription which was being monitored. ++ * inotify_lock must be held when calling. + */ +-gboolean ++static gboolean + ih_sub_cancel (ih_sub_t * sub) + { +- G_LOCK(inotify_lock); +- +- + if (!sub->cancelled) + { + IH_W("cancelling %s\n", sub->pathname); +@@ -140,7 +138,6 @@ ih_sub_cancel (ih_sub_t * sub) + sub_list = g_list_remove (sub_list, sub); + } + +- G_UNLOCK(inotify_lock); + return TRUE; + } + +diff --git a/server/inotify-helper.h b/server/inotify-helper.h +index 5d3b6d0..d36b5fd 100644 +--- a/server/inotify-helper.h ++++ b/server/inotify-helper.h +@@ -34,7 +34,6 @@ gboolean ih_startup (event_callback_t ecb, + found_callback_t fcb); + gboolean ih_running (void); + gboolean ih_sub_add (ih_sub_t *sub); +-gboolean ih_sub_cancel (ih_sub_t *sub); + + /* Return FALSE from 'f' if the subscription should be cancelled */ + void ih_sub_foreach (void *callerdata, gboolean (*f)(ih_sub_t *sub, void *callerdata)); +-- +1.7.7.2 + diff --git a/code/PKGBUILD b/code/PKGBUILD new file mode 100644 index 0000000..194c632 --- /dev/null +++ b/code/PKGBUILD @@ -0,0 +1,56 @@ +# Maintainer: Pekka Helenius +# Contributor: Abhishek Dasgupta +# Contributor: Pulphix + +pkgname=gamin +pkgver=0.1.10 +pkgrel=10 +pkgdesc='File and directory monitoring system defined to be a subset of the FAM (File Alteration Monitor)' +url='http://www.gnome.org/~veillard/gamin' +license=('GPL') +arch=('any') +depends=('glib2') +makedepends=('python') +optdepends=('python: for the python module') +provides=('fam') +conflicts=('fam') +source=("$url/sources/${pkgname}-${pkgver}.tar.gz" + 'fix-deprecated-const.patch' + '18_gam_server_deadlocks.patch' + '0001-Poll-files-on-nfs4.patch' + 'patch_python3.patch' +) +sha512sums=('21bfe6fcf8fb3117cd5a08c8ce3b8d0d1dd23e478e60a95b76c20d02cc29b050dde086578d81037990484ff891c3e104d2cbbf3d294b4a79346b14a0cae075bb' + 'c4c10bee70c7231db395cbfe5bdf513ade6be599a11a9d35888ddfaca42d619fe2b5e87c2b2bab469ea98ba718bc01711252313ba5f53c392379b669f5b2902b' + 'ae2d3f3cd16e2da05836cbb2f21527896db5d5067ef4b120e943693234a685527eff528955ed80120265ca70e04a88cc28413cc34311d6faa068c620339fad38' + 'dcb23fd68e106a1b578235ef0b01b49773908ca6ded706610103f880f77a2aa0b0403cb720b9c6b062bac71e9d66cd2288b489c558839fc23295b18635bf399f' + '7368286df3b2db9df02a585150bef5b9aa7f0b80cc913a7867739ccc1abf3f45674515c02fad9423607b9b7266a61884f01e43b89d29b16afbbf7524e75f21e7' + '323fa143947b7df0b746cac980f9a610f364883c94fdc3800f3cee2e3bfa6e5945cbff0a865f8a3349441127cc450a7be04be2073772fb3c6af227637542fa43' + '2cd2c49b588147f93753c6bb46afa9438cf0f63ff1a61761ae09b534658aceb0fd5f0eab9c7037bc3c890e63cba9407499c5b9c715a7568f2ec94f4565a6e40f' + '596efc8a9bb98bbeacb11a1995f54146fb68fefae28fa28db0728c47d61f10009b8aa0d91c54a4c73e5c6478b8d049c942a00131cbb5342a01f83c2dda103858' + 'e5575ac8d5908926d5c7d26076b14980b328cd4caa695f8c2cdb21999dd4868da9c90d8d9c469bf1fe316ac752c2637b0525a79f9b9188778c82f6f96beecaac') + +prepare() { + cd $pkgname-$pkgver + + # https://bugs.archlinux.org/task/33642 + patch -Np1 -i ../18_gam_server_deadlocks.patch + + patch -Np1 -i ../fix-deprecated-const.patch + patch -Np1 -i ../0001-Poll-files-on-nfs4.patch + + patch -Np1 -i ../patch_python3.patch +} + +build() { + cd $pkgname-$pkgver + ./configure --prefix=/usr --disable-static --with-threads \ + --disable-debug-api --disable-debug --libexecdir=/usr/lib/gamin \ + --with-python=/usr/bin/python + make +} + +package() { + cd $pkgname-$pkgver + make DESTDIR="$pkgdir" install +} diff --git a/code/fix-deprecated-const.patch b/code/fix-deprecated-const.patch new file mode 100644 index 0000000..3d5f613 --- /dev/null +++ b/code/fix-deprecated-const.patch @@ -0,0 +1,56 @@ +Description: Don't use deprecated G_CONST_RETURN. Fixes building with newer glib versions. +Author: Matthias Klose +Bug-Ubuntu: https://launchpad.net/bugs/829504 + +Index: gamin/server/gam_node.c +=================================================================== +--- gamin.orig/server/gam_node.c 2011-10-18 16:09:04.873780685 +0200 ++++ gamin/server/gam_node.c 2011-10-18 16:09:01.965780543 +0200 +@@ -122,7 +122,7 @@ + * it has finished with the string. If it must keep it longer, it + * should makes its own copy. The returned string must not be freed. + */ +-G_CONST_RETURN char * ++const char * + gam_node_get_path(GamNode * node) + { + g_assert(node); +Index: gamin/server/gam_node.h +=================================================================== +--- gamin.orig/server/gam_node.h 2011-10-18 16:09:04.729780677 +0200 ++++ gamin/server/gam_node.h 2011-10-18 16:09:01.961780544 +0200 +@@ -58,7 +58,7 @@ + void gam_node_set_is_dir (GamNode *node, + gboolean is_dir); + +-G_CONST_RETURN char *gam_node_get_path (GamNode *node); ++const char *gam_node_get_path (GamNode *node); + + GList *gam_node_get_subscriptions (GamNode *node); + +Index: gamin/server/gam_subscription.c +=================================================================== +--- gamin.orig/server/gam_subscription.c 2011-10-18 16:09:04.817780682 +0200 ++++ gamin/server/gam_subscription.c 2011-10-18 16:09:01.965780543 +0200 +@@ -141,7 +141,7 @@ + * @param sub the GamSubscription + * @returns The path being monitored. It should not be freed. + */ +-G_CONST_RETURN char * ++const char * + gam_subscription_get_path(GamSubscription * sub) + { + if (sub == NULL) +Index: gamin/server/gam_subscription.h +=================================================================== +--- gamin.orig/server/gam_subscription.h 2011-10-18 16:09:04.929780687 +0200 ++++ gamin/server/gam_subscription.h 2011-10-18 16:09:01.965780543 +0200 +@@ -21,7 +21,7 @@ + + int gam_subscription_get_reqno (GamSubscription *sub); + +-G_CONST_RETURN char *gam_subscription_get_path (GamSubscription *sub); ++const char *gam_subscription_get_path (GamSubscription *sub); + + GamListener *gam_subscription_get_listener (GamSubscription *sub); + diff --git a/code/gamin-0.1.10.tar.gz b/code/gamin-0.1.10.tar.gz new file mode 100644 index 0000000..58a1b0d Binary files /dev/null and b/code/gamin-0.1.10.tar.gz differ diff --git a/code/patch_python3.patch b/code/patch_python3.patch new file mode 100644 index 0000000..aecd638 --- /dev/null +++ b/code/patch_python3.patch @@ -0,0 +1,5582 @@ +--- a/gamin.spec 2020-04-28 10:15:58.288728880 +0300 ++++ b/gamin.spec 2020-04-28 10:16:15.368816041 +0300 +@@ -32,7 +32,7 @@ + Summary: Python bindings for the gamin library + Group: Development/Libraries + Requires: gamin = %{version} +-Requires: %{_libdir}/python%(echo `python -c "import sys; print sys.version[0:3]"`) ++Requires: %{_libdir}/python%(echo `python -c "import sys; print(sys.version[0:3])"`) + + %description python + The gamin-python package contains a module that allow monitoring of +--- a/python/tests/basic2.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/basic2.py 2020-04-28 09:21:56.928853041 +0300 +@@ -16,4 +16,4 @@ + mon.disconnect() + del mon + +-print "OK" ++print("OK") +--- a/python/tests/basic3.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/basic3.py 2020-04-28 09:22:48.185783579 +0300 +@@ -27,7 +27,7 @@ + shutil.rmtree ("temp_dir", True) + os.mkdir ("temp_dir") + if top != 4: +- print "Error: top monitor got %d events insteads of 4" % (top) ++ print("Error: top monitor got %d events insteads of 4" % (top)) + sys.exit(1) + +-print "OK" ++print("OK") +--- a/python/tests/basic4.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/basic4.py 2020-04-28 09:23:35.479360223 +0300 +@@ -13,10 +13,10 @@ + + def callback(path, event): + global top, expect, ok +- print "Got callback: %s, %s" % (path, event) ++ print("Got callback: %s, %s" % (path, event)) + if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -36,8 +36,8 @@ + del mon + shutil.rmtree ("temp_dir", True) + if top != 4: +- print "Error: top monitor got %d events insteads of 4" % (top) ++ print("Error: top monitor got %d events insteads of 4" % (top)) + sys.exit(1) + + if ok: +- print "OK" ++ print("OK") +--- a/python/tests/basic5.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/basic5.py 2020-04-28 09:24:24.129610391 +0300 +@@ -15,8 +15,8 @@ + global top, expect, ok + # print "Got callback: %s, %s" % (path, event) + if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -34,8 +34,8 @@ + del mon + shutil.rmtree ("temp_dir", True) + if top != 4: +- print "Error: top monitor got %d events insteads of 4" % (top) ++ print("Error: top monitor got %d events insteads of 4" % (top)) + sys.exit(1) + + if ok: +- print "OK" ++ print("OK") +--- a/python/tests/basic6.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/basic6.py 2020-04-28 09:25:17.209883211 +0300 +@@ -14,8 +14,8 @@ + global top, expect, ok + # print "Got callback: %s, %s" % (path, event) + if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -32,8 +32,8 @@ + del mon + shutil.rmtree ("temp_dir", True) + if top != 3: +- print "Error: top monitor got %d events insteads of 3" % (top) ++ print("Error: top monitor got %d events insteads of 3" % (top)) + sys.exit(1) + + if ok: +- print "OK" ++ print("OK") +--- a/python/tests/basic.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/basic.py 2020-04-28 09:25:44.686691054 +0300 +@@ -20,6 +20,6 @@ + mon.disconnect() + del mon + if nb_callbacks > 2: +- print 'OK' ++ print('OK') + else: +- print 'error' ++ print('error') +--- a/python/tests/bigfile.py 2020-04-28 10:04:16.718483188 +0300 ++++ b/python/tests/bigfile.py 2020-04-28 10:08:29.099770201 +0300 +@@ -11,16 +11,16 @@ + expect = [gamin.GAMExists, gamin.GAMEndExist, gamin.GAMDeleted] + def callback(path, event): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) + os.mkdir ("temp_dir") + fd = os.open("temp_dir/bigfile", os.O_WRONLY | os.O_CREAT) +-os.lseek(fd, 2200000000L, 0) ++os.lseek(fd, 2200000000, 0) + os.write(fd, "foo") + os.close(fd) + +@@ -36,8 +36,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 3: +- print "Error: top monitor got %d events insteads of 3" % (top) ++ print("Error: top monitor got %d events insteads of 3" % (top)) + sys.exit(1) + + if ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify10.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify10.py 2020-04-28 09:32:18.885379969 +0300 +@@ -22,30 +22,30 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (expect2[top2], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect2[top2], event)) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -72,10 +72,10 @@ + shutil.rmtree ("temp_dir", True) + + if top != 4: +- print "Error: monitor got %d events insteads of 4" % (top) ++ print("Error: monitor got %d events insteads of 4" % (top)) + elif top2 != 2: +- print "Error: monitor got %d events insteads of 2" % (top2) ++ print("Error: monitor got %d events insteads of 2" % (top2)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify11.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify11.py 2020-04-28 09:33:43.045811250 +0300 +@@ -23,30 +23,30 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (expect2[top2], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect2[top2], event)) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -76,10 +76,10 @@ + shutil.rmtree ("temp_dir", True) + + if top != 5: +- print "Error: monitor got %d events insteads of 5" % (top) ++ print("Error: monitor got %d events insteads of 5" % (top)) + elif top2 != 3: +- print "Error: monitor got %d events insteads of 3" % (top2) ++ print ("Error: monitor got %d events insteads of 3" % (top2)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify12.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify12.py 2020-04-28 09:35:57.416499538 +0300 +@@ -23,30 +23,30 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (expect2[top2], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect2[top2], event)) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -75,10 +75,10 @@ + shutil.rmtree ("temp_dir", True) + + if top != 4: +- print "Error: monitor got %d events insteads of 4" % (top) ++ print("Error: monitor got %d events insteads of 4" % (top)) + elif top2 != 5: +- print "Error: monitor2 got %d events insteads of 5" % (top2) ++ print("Error: monitor2 got %d events insteads of 5" % (top2)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify13.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify13.py 2020-04-28 09:36:58.396811829 +0300 +@@ -27,40 +27,40 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (expect2[top2], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect2[top2], event)) ++ ok = 0 + top2 = top2 + 1 + + def callback3(path, event, which): + global top3, expect3, ok +-# print "Got callback3: %s, %s" % (path, event) ++# print("Got callback3: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect3[top3] != event: +- print "Error got event %d expected %d" % (expect3[top3], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect3[top3], event)) ++ ok = 0 + top3 = top3 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -94,12 +94,12 @@ + shutil.rmtree ("temp_dir", True) + + if top != 4: +- print "Error: monitor got %d events insteads of 4" % (top) ++ print("Error: monitor got %d events insteads of 4" % (top)) + elif top2 != 5: +- print "Error: monitor2 got %d events insteads of 5" % (top2) ++ print("Error: monitor2 got %d events insteads of 5" % (top2)) + elif top3 != 4: +- print "Error: monitor3 got %d events insteads of 4" % (top3) ++ print("Error: monitor3 got %d events insteads of 4" % (top3)) + elif dbg != 6 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify15.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify15.py 2020-04-28 09:37:53.067091790 +0300 +@@ -18,26 +18,26 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + # ignore events on a, focuse on b only + if path[-2:] == "/a": + return + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -92,8 +92,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 3: +- print "Error: monitor got %d events insteads of 3" % (top) ++ print("Error: monitor got %d events insteads of 3" % (top)) + elif dbg != 5 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 5" % (dbg) ++ print("Error: debug got %d events insteads of 5" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify2.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify2.py 2020-04-28 09:38:30.887285380 +0300 +@@ -18,23 +18,23 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +- print "Got debug %s, %s, %s" % (path, type, data) ++ print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -56,8 +56,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 2: +- print "Error: monitor got %d events insteads of 2" % (top) ++ print("Error: monitor got %d events insteads of 2" % (top)) + elif dbg != 2 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 2" % (dbg) ++ print("Error: debug got %d events insteads of 2" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify3.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify3.py 2020-04-28 09:40:47.691318954 +0300 +@@ -19,23 +19,23 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-10:] != "temp_dir/a": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (db_expect[dbg], type) +- ok = 0 ++ print("Error got debug event %d expected %d" % (db_expect[dbg], type)) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + +@@ -60,8 +60,8 @@ + del mon + + if top != 3: +- print "Error: monitor got %d events insteads of 2" % (top) ++ print("Error: monitor got %d events insteads of 2" % (top)) + elif dbg != 2 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 2" % (dbg) ++ print("Error: debug got %d events insteads of 2" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify4.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify4.py 2020-04-28 09:41:22.311496122 +0300 +@@ -18,23 +18,23 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (db_expect[dbg], type) +- ok = 0 ++ print("Error got debug event %d expected %d" % (db_expect[dbg], type)) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -55,8 +55,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 2: +- print "Error: monitor got %d events insteads of 2" % (top) ++ print("Error: monitor got %d events insteads of 2" % (top)) + elif dbg != 2 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 2" % (dbg) ++ print("Error: debug got %d events insteads of 2" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify5.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify5.py 2020-04-28 09:41:22.321496173 +0300 +@@ -19,23 +19,23 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -61,8 +61,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 4: +- print "Error: monitor got %d events insteads of 4" % (top) ++ print("Error: monitor got %d events insteads of 4" % (top)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify6.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify6.py 2020-04-28 09:41:22.331496225 +0300 +@@ -19,26 +19,26 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if dbg < 2 and path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if dbg >= 2 and path[-10:] != "temp_dir/a": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -64,8 +64,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 4: +- print "Error: monitor got %d events insteads of 4" % (top) ++ print("Error: monitor got %d events insteads of 4" % (top)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify7.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify7.py 2020-04-28 09:50:04.574149660 +0300 +@@ -15,52 +15,52 @@ + dbg = 0 + db_expect = [ 51, # directory watch + 53, # file watch count incremented +- 53, # file disapear count decremented +- 53, # file recreated +- 53, # removal of watch on file +- 52 # removal of watch on directory +- ] ++ 53, # file disapear count decremented ++ 53, # file recreated ++ 53, # removal of watch on file ++ 52 # removal of watch on directory ++ ] + top_f = 0 + expect_f = [gamin.GAMExists, gamin.GAMEndExist, gamin.GAMDeleted, + gamin.GAMCreated] + top_d = 0 + expect_d = [gamin.GAMExists, # directory exists + gamin.GAMExists, # file a exists +- gamin.GAMEndExist,# end listing +- gamin.GAMDeleted, # file a removed ++ gamin.GAMEndExist,# end listing ++ gamin.GAMDeleted, # file a removed + gamin.GAMCreated # file a created +- ] ++ ] + + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback_file(path, event): + global top_f, expect_f, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect_f[top_f] != event: +- print "Error got file event %d expected %d" % (expect_f[top_f], event) +- ok = 0 ++ print("Error got file event %d expected %d" % (expect_f[top_f], event)) ++ ok = 0 + top_f = top_f + 1 + + def callback_dir(path, event): + global top_d, expect_d, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect_d[top_d] != event: +- print "Error got dir event %d expected %d" % (expect_d[top_d], event) +- ok = 0 ++ print("Error got dir event %d expected %d" % (expect_d[top_d], event)) ++ ok = 0 + top_d = top_d + 1 + + shutil.rmtree ("temp_dir", True) +@@ -88,10 +88,10 @@ + shutil.rmtree ("temp_dir", True) + + if top_f != 4: +- print "Error: file monitor got %d events insteads of 4" % (top_f) ++ print("Error: file monitor got %d events insteads of 4" % (top_f)) + if top_d != 5: +- print "Error: dir monitor got %d events insteads of 4" % (top_d) ++ print("Error: dir monitor got %d events insteads of 4" % (top_d)) + elif dbg != 6 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 6" % (dbg) ++ print("Error: debug got %d events insteads of 6" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify8.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify8.py 2020-04-28 09:41:22.338162925 +0300 +@@ -23,30 +23,30 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (expect2[top2], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect2[top2], event)) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -74,10 +74,10 @@ + shutil.rmtree ("temp_dir", True) + + if top != 5: +- print "Error: monitor got %d events insteads of 5" % (top) ++ print("Error: monitor got %d events insteads of 5" % (top)) + elif top2 != 3: +- print "Error: monitor got %d events insteads of 3" % (top2) ++ print("Error: monitor got %d events insteads of 3" % (top2)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify9.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify9.py 2020-04-28 09:41:22.348162976 +0300 +@@ -23,30 +23,30 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (expect2[top2], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect2[top2], event)) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -73,10 +73,10 @@ + shutil.rmtree ("temp_dir", True) + + if top != 4: +- print "Error: monitor got %d events insteads of 4" % (top) ++ print("Error: monitor got %d events insteads of 4" % (top)) + elif top2 != 2: +- print "Error: monitor got %d events insteads of 2" % (top2) ++ print("Error: monitor got %d events insteads of 2" % (top2)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/dnotify.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/dnotify.py 2020-04-28 09:41:57.501676222 +0300 +@@ -19,23 +19,23 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-10:] != "temp_dir/a": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (db_expect[dbg], type) +- ok = 0 ++ print("Error got debug event %d expected %d" % (db_expect[dbg], type)) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + +@@ -58,8 +58,8 @@ + shutil.rmtree ("temp_dir", True) + + if top != 2: +- print "Error: monitor got %d events insteads of 2" % (top) ++ print("Error: monitor got %d events insteads of 2" % (top)) + elif dbg != 2 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 2" % (dbg) ++ print("Error: debug got %d events insteads of 2" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/flood2.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/flood2.py 2020-04-28 09:43:06.445362352 +0300 +@@ -37,15 +37,15 @@ + global block + + threads = threads + 1 +-# print "%s active" % (filename) ++# print("%s active" % (filename)) + f = open(filename, "w") + f.write(block) + j = 0 + while j < 50: + wait_ms(100) +- j = j + 1 +- f.write(block) +-# print "%s quiet" % (filename) ++ j = j + 1 ++ f.write(block) ++# print("%s quiet" % (filename)) + f.close() + wait_ms(8000) + threads = threads - 1 +@@ -63,43 +63,43 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + # on may see one or two bursts + if dbg == 4 and type == 53: + dbg = 6 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if top < 2: +- if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ if expect[top] != event: ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + elif event != gamin.GAMChanged: +- print "Error got event %d expected %d" % (event, gamin.GAMChanged) +- ok = 0 ++ print("Error got event %d expected %d" % (event, gamin.GAMChanged)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + # ignore the Changed events generated by modifying a + if event == gamin.GAMAcknowledge: + return + if event == gamin.GAMChanged: + return + if expect2[top2] != event: +- print "Error got event %d expected %d" % (event, expect2[top2]) +- ok = 0 ++ print("Error got event %d expected %d" % (event, expect2[top2])) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -121,7 +121,7 @@ + i = i + 1 + wait_ms(100) + mon.handle_events() +-# print "created b" ++# print("created b") + f = open("temp_dir/b", "w").close() + while i < 50: + i = i + 1 +@@ -129,7 +129,7 @@ + mon.handle_events() + mon.handle_events() + os.unlink("temp_dir/b") +-# print "deleted b" ++# print("deleted b") + + # wait until the thread finishes, collecting events + wait_ms(100) +@@ -137,7 +137,7 @@ + mon.handle_events() + wait_ms(100) + +-#print "all threads terminated, exiting ..." ++#print("all threads terminated, exiting ...") + + mon.handle_events() + mon.stop_watch("temp_dir/a") +@@ -149,12 +149,12 @@ + shutil.rmtree ("temp_dir", True) + + if top <= 2: +- print "Error: monitor got only %d events" % (top) ++ print("Error: monitor got only %d events" % (top)) + elif top >= 28: +- print "Error: event flow didn't worked properly, gor %d events" % (top) ++ print("Error: event flow didn't worked properly, gor %d events" % (top)) + elif top2 != 5: +- print "Error: monitor2 got %d events instead of %d" % (top2, 5) ++ print("Error: monitor2 got %d events instead of %d" % (top2, 5)) + elif dbg != 8 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 8" % (dbg) ++ print("Error: debug got %d events insteads of 8" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/flood3.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/flood3.py 2020-04-28 09:43:06.458695754 +0300 +@@ -37,15 +37,15 @@ + global block + + threads = threads + 1 +-# print "%s active" % (filename) ++# print("%s active" % (filename)) + f = open(filename, "w") + f.write(block) + j = 0 + while j < 50: + wait_ms(100) +- j = j + 1 +- f.write(block) +-# print "%s quiet" % (filename) ++ j = j + 1 ++ f.write(block) ++# print("%s quiet" % (filename)) + f.close() + time.sleep(8) + threads = threads - 1 +@@ -62,41 +62,41 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if top < 2: +- if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ if expect[top] != event: ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + elif event != gamin.GAMChanged: +- print "Error got event %d expected %d" % (event, gamin.GAMChanged) +- ok = 0 ++ print("Error got event %d expected %d" % (event, gamin.GAMChanged)) ++ ok = 0 + top = top + 1 + + def callback2(path, event, which): + global top2, expect2, ok +-# print "Got callback2: %s, %s" % (path, event) ++# print("Got callback2: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if top2 < 2: +- if expect2[top2] != event: +- print "Error got event %d expected %d" % (event, expect2[top2]) +- ok = 0 ++ if expect2[top2] != event: ++ print("Error got event %d expected %d" % (event, expect2[top2])) ++ ok = 0 + elif event != gamin.GAMChanged: +- print "Error got event %d expected %d" % (event, gamin.GAMChanged) +- ok = 0 ++ print("Error got event %d expected %d" % (event, gamin.GAMChanged)) ++ ok = 0 + top2 = top2 + 1 + + shutil.rmtree ("temp_dir", True) +@@ -127,7 +127,7 @@ + mon.handle_events() + time.sleep(1) + +-#print "all threads terminated, exiting ..." ++#print("all threads terminated, exiting ...") + + mon.handle_events() + mon.stop_watch("temp_dir/a") +@@ -139,14 +139,14 @@ + shutil.rmtree ("temp_dir", True) + + if top <= 2: +- print "Error: monitor got only %d events" % (top) ++ print("Error: monitor got only %d events" % (top)) + elif top >= 20: +- print "Error: event flow didn't worked properly, got %d events" % (top) ++ print("Error: event flow didn't worked properly, got %d events" % (top)) + elif top2 <= 2: +- print "Error: monitor got only %d events" % (top2) ++ print("Error: monitor got only %d events" % (top2)) + elif top2 >= 20: +- print "Error: event flow didn't worked properly, got %d events 2" % (top2) ++ print("Error: event flow didn't worked properly, got %d events 2" % (top2)) + elif dbg != 6 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 6" % (dbg) ++ print("Error: debug got %d events insteads of 6" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/flood4.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/flood4.py 2020-04-28 09:43:06.468695805 +0300 +@@ -36,20 +36,20 @@ + threads = threads + 1 + i = 0 + while i < 15: +- f = open(directory + '/a', "w").close() +- f = open(directory + '/b', "w").close() +- f = open(directory + '/c', "w").close() ++ f = open(directory + '/a', "w").close() ++ f = open(directory + '/b', "w").close() ++ f = open(directory + '/c', "w").close() + wait_ms(100) +- os.unlink(directory + '/a') +- f = open(directory + '/d', "w").close() +- os.unlink(directory + '/b') +- f = open(directory + '/e', "w").close() ++ os.unlink(directory + '/a') ++ f = open(directory + '/d', "w").close() ++ os.unlink(directory + '/b') ++ f = open(directory + '/e', "w").close() + wait_ms(100) +- os.unlink(directory + '/c') +- os.unlink(directory + '/d') +- os.unlink(directory + '/e') ++ os.unlink(directory + '/c') ++ os.unlink(directory + '/d') ++ os.unlink(directory + '/e') + wait_ms(100) +- i = i + 1 ++ i = i + 1 + wait_ms(8000) + threads = threads - 1 + thread.exit() +@@ -63,28 +63,28 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if top < 2: +- if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ if expect[top] != event: ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + elif event != gamin.GAMCreated and event != gamin.GAMDeleted and \ + event != gamin.GAMChanged: +- print "Error got event %d" % (event) +- ok = 0 ++ print("Error got event %d" % (event)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -101,7 +101,7 @@ + mon.handle_events() + wait_ms(100) + +-#print "all threads terminated, exiting ..." ++#print("all threads terminated, exiting ...") + + mon.stop_watch("temp_dir") + time.sleep(1) +@@ -111,10 +111,10 @@ + shutil.rmtree ("temp_dir", True) + + if top <= 2: +- print "Error: monitor got only %d events" % (top) ++ print("Error: monitor got only %d events" % (top)) + elif top >= 60: +- print "Error: event flow didn't worked properly, gor %d events" % (top) ++ print("Error: event flow didn't worked properly, gor %d events" % (top)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/flood.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/flood.py 2020-04-28 09:44:19.372402209 +0300 +@@ -34,15 +34,15 @@ + global block + + threads = threads + 1 +-# print "%s active" % (filename) ++# print("%s active" % (filename)) + f = open(filename, "w") + f.write(block) + i = 0 + while i < 50: + wait_ms(100) +- i = i + 1 +- f.write(block) +-# print "%s quiet" % (filename) ++ i = i + 1 ++ f.write(block) ++# print("%s quiet" % (filename)) + wait_ms(10000) + f.write(block) + f.close() +@@ -59,27 +59,27 @@ + def debug(path, type, data): + global dbg, db_expect, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + if path[-8:] != "temp_dir": +- print "Error got debug path unexpected %s" % (path) +- ok = 0 ++ print("Error got debug path unexpected %s" % (path)) ++ ok = 0 + if db_expect[dbg] != type: +- print "Error got debug event %d expected %d" % (type, db_expect[dbg]) +- ok = 0 ++ print("Error got debug event %d expected %d" % (type, db_expect[dbg])) ++ ok = 0 + dbg = dbg + 1 + + def callback(path, event, which): + global top, expect, ok +- print "Got callback: %s, %s" % (path, event) ++ print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if top < 2: +- if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ if expect[top] != event: ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + elif event != gamin.GAMChanged: +- print "Error got event %d expected %d" % (event, gamin.GAMChanged) +- ok = 0 ++ print("Error got event %d expected %d" % (event, gamin.GAMChanged)) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -97,7 +97,7 @@ + mon.handle_events() + wait_ms(100) + +-#print "all threads terminated, exiting ..." ++#print("all threads terminated, exiting ...") + + mon.stop_watch("temp_dir/a") + time.sleep(1) +@@ -107,10 +107,10 @@ + shutil.rmtree ("temp_dir", True) + + if top <= 2: +- print "Error: monitor got only %d events" % (top) ++ print("Error: monitor got only %d events" % (top)) + elif top >= 15: +- print "Error: event flow didn't worked properly, gor %d events" % (top) ++ print("Error: event flow didn't worked properly, gor %d events" % (top)) + elif dbg != 4 and gamin.has_debug_api == 1: +- print "Error: debug got %d events insteads of 4" % (dbg) ++ print("Error: debug got %d events insteads of 4" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") +--- a/python/tests/readonly.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/readonly.py 2020-04-28 09:48:02.523532294 +0300 +@@ -12,10 +12,10 @@ + + def callback(path, event): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if expect[top] != event: +- print "Error got event %d expected %d" % (event, expect[top]) +- ok = 0 ++ print("Error got event %d expected %d" % (event, expect[top])) ++ ok = 0 + top = top + 1 + + shutil.rmtree ("temp_dir", True) +@@ -29,11 +29,11 @@ + mon.stop_watch("temp_dir") + mon.disconnect() + del mon +-os.chmod ("temp_dir", 0755) ++os.chmod ("temp_dir", 755) + shutil.rmtree ("temp_dir", True) + if top != 2: +- print "Error: top monitor got %d events insteads of 4" % (top) ++ print("Error: top monitor got %d events insteads of 4" % (top)) + sys.exit(1) + + if ok: +- print "OK" ++ print("OK") +--- a/python/tests/level.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/level.patched.py 2020-04-28 11:17:24.737888018 +0300 +@@ -10,7 +10,7 @@ + sub = 0 + def callback(path, event, which): + global top, sub +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if which == 0: + top = top + 1 + elif which == 1: +@@ -27,7 +27,7 @@ + mon.handle_events() + mon.stop_watch("temp_dir") + if top != 3: +- print "Error: top monitor got %d events insteads of 3" % (top) ++ print("Error: top monitor got %d events insteads of 3" % (top)) + time.sleep(1) + os.mkdir ("temp_dir/a/b") + time.sleep(1) +@@ -38,6 +38,6 @@ + shutil.rmtree ("temp_dir", True) + + if sub != 3: +- print "Error: sub monitor got %d events insteads of 3" % (sub) ++ print("Error: sub monitor got %d events insteads of 3" % (sub)) + else: +- print "OK" ++ print("OK") +--- a/python/tests/multiple2.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/multiple2.patched.py 2020-04-28 09:44:44.835865847 +0300 +@@ -11,11 +11,11 @@ + + def callback(path, event, number): + global nb_callbacks +-# print "Got callback: %d, %s, %s" % (number, path, event) ++# print("Got callback: %d, %s, %s" % (number, path, event)) + if nb_callbacks.has_key(number): + nb_callbacks[number] = nb_callbacks[number] + 1 + else: +- nb_callbacks[number] = 1 ++ nb_callbacks[number] = 1 + + shutil.rmtree ("temp_dir", True) + os.mkdir ("temp_dir") +@@ -47,11 +47,11 @@ + i = 0 + while i < 10: + if not nb_callbacks.has_key(i): +- print "Error: monitor %d didn't got events" % (i) +- sys.exit(1) ++ print("Error: monitor %d didn't got events" % (i)) ++ sys.exit(1) + if nb_callbacks[i] != 4: +- print "Error: monitor %d got %d out of 4 events" % (i, nb_callbacks[i]) +- sys.exit(1) ++ print("Error: monitor %d got %d out of 4 events" % (i, nb_callbacks[i])) ++ sys.exit(1) + i = i + 1 + + shutil.rmtree ("temp_dir/a", True) +@@ -64,9 +64,9 @@ + shutil.rmtree ("temp_dir", True) + + if not nb_callbacks.has_key(11): +- print "Error: main monitor didn't got events" ++ print("Error: main monitor didn't got events") + sys.exit(1) + if nb_callbacks[11] != 6: +- print "Error: main monitor got %d out of 6 events" % (nb_callbacks[11]) ++ print("Error: main monitor got %d out of 6 events" % (nb_callbacks[11])) + sys.exit(1) +-print "OK" ++print("OK") +--- a/python/tests/multiple3.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/multiple3.patched.py 2020-04-28 09:48:53.360455909 +0300 +@@ -21,25 +21,25 @@ + global expect1, nb1 + global expect2, nb2 + +-# print "Got callback on %d: %s, %s" % (which, path, event) ++# print("Got callback on %d: %s, %s" % (which, path, event)) + if event == gamin.GAMAcknowledge: + return + if which == 0: + if event != expect0[nb0]: +- print "Error: monitor %d got event %d expected %d" % (which, event, +- expect0[nb0]) ++ print("Error: monitor %d got event %d expected %d" % (which, event, ++ expect0[nb0])) + ok = 0 + nb0 = nb0 + 1 + elif which == 1: + if event != expect1[nb1]: +- print "Error: monitor %d got event %d expected %d" % (which, event, +- expect1[nb1]) ++ print("Error: monitor %d got event %d expected %d" % (which, event, ++ expect1[nb1])) + ok = 0 + nb1 = nb1 + 1 + elif which == 2: + if event != expect2[nb2]: +- print "Error: monitor %d got event %d expected %d" % (which, event, +- expect2[nb2]) ++ print("Error: monitor %d got event %d expected %d" % (which, event, ++ expect2[nb2])) + ok = 0 + nb2 = nb2 + 1 + +@@ -72,13 +72,13 @@ + shutil.rmtree ("temp_dir", True) + + if nb0 != len(expect0): +- print "Error: monitor 0 got %d events, expecting %d" % (nb0, len(expect0)) ++ print("Error: monitor 0 got %d events, expecting %d" % (nb0, len(expect0))) + ok = 0 + if nb1 != len(expect1): +- print "Error: monitor 1 got %d events, expecting %d" % (nb1, len(expect1)) ++ print("Error: monitor 1 got %d events, expecting %d" % (nb1, len(expect1))) + ok = 0 + if nb2 != len(expect2): +- print "Error: monitor 2 got %d events, expecting %d" % (nb2, len(expect2)) ++ print("Error: monitor 2 got %d events, expecting %d" % (nb2, len(expect2))) + ok = 0 + if ok: +- print "OK" ++ print("OK") +--- a/python/tests/multiple.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/multiple.patched.py 2020-04-28 09:45:02.162621170 +0300 +@@ -11,11 +11,11 @@ + + def callback(path, event, number): + global nb_callbacks +-# print "Got callback: %d, %s, %s" % (number, path, event) ++# print("Got callback: %d, %s, %s" % (number, path, event)) + if nb_callbacks.has_key(number): + nb_callbacks[number] = nb_callbacks[number] + 1 + else: +- nb_callbacks[number] = 1 ++ nb_callbacks[number] = 1 + + shutil.rmtree ("temp_dir", True) + os.mkdir ("temp_dir") +@@ -44,11 +44,11 @@ + i = 0 + while i < 10: + if not nb_callbacks.has_key(i): +- print "Error: monitor %d didn't got events" % (i) +- sys.exit(1) ++ print("Error: monitor %d didn't got events" % (i)) ++ sys.exit(1) + if nb_callbacks[i] != 4: +- print "Error: monitor %d got %d out of 4 events" % (i, nb_callbacks[i]) +- sys.exit(1) ++ print("Error: monitor %d got %d out of 4 events" % (i, nb_callbacks[i])) ++ sys.exit(1) + i = i + 1 + +-print "OK" ++print("OK") +--- a/python/tests/noexists.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/noexists.patched.py 2020-04-28 09:45:33.372779922 +0300 +@@ -10,7 +10,7 @@ + + def callback(path, event): + global nb_callbacks +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + nb_callbacks = nb_callbacks + 1 + + shutil.rmtree ("temp_dir", True) +@@ -22,7 +22,7 @@ + time.sleep(1) + ret = mon.event_pending() + if ret != 0: +- print 'error : no event expected' ++ print('error : no event expected') + shutil.rmtree ("temp_dir", True) + sys.exit(1) + +@@ -30,7 +30,7 @@ + time.sleep(1) + ret = mon.event_pending() + if ret != 1: +- print 'error : created event expected' ++ print('error : created event expected') + shutil.rmtree ("temp_dir", True) + sys.exit(1) + +@@ -39,7 +39,7 @@ + time.sleep(1) + ret = mon.event_pending() + if ret != 1: +- print 'error : deleted event expected' ++ print('error : deleted event expected') + shutil.rmtree ("temp_dir", True) + sys.exit(1) + +@@ -48,6 +48,6 @@ + mon.disconnect() + del mon + if nb_callbacks == 2: +- print 'OK' ++ print('OK') + else: +- print 'error' ++ print('error') +--- a/python/tests/nokernel.py 2020-04-28 09:06:40.054123779 +0300 ++++ b/python/tests/nokernel.patched.py 2020-04-28 09:45:33.379446621 +0300 +@@ -18,24 +18,24 @@ + def debug(path, type, data): + global dbg, ok + +-# print "Got debug %s, %s, %s" % (path, type, data) ++# print("Got debug %s, %s, %s" % (path, type, data)) + dbg = dbg + 1 + ok = 0 + + def callback(path, event, which): + global top, expect, ok +-# print "Got callback: %s, %s" % (path, event) ++# print("Got callback: %s, %s" % (path, event)) + if event == gamin.GAMAcknowledge: + return + if expect[top] != event: +- print "Error got event %d expected %d" % (expect[top], event) +- ok = 0 ++ print("Error got event %d expected %d" % (expect[top], event)) ++ ok = 0 + top = top + 1 + + + if not os.access('/media/test', os.R_OK | os.X_OK | os.W_OK): +- print "missing access to /media/test, test skipped" +- print "OK" ++ print("missing access to /media/test, test skipped") ++ print("OK") + sys.exit(0) + + shutil.rmtree ("/media/test/a", True) +@@ -53,10 +53,10 @@ + del mon + + if top != 3: +- print "Error: monitor got %d events insteads of 3" % (top) ++ print("Error: monitor got %d events insteads of 3" % (top)) + elif dbg != 0 and gamin.has_debug_api == 1: +- print "Error: debug got %d kernel events insteads of 0" % (dbg) ++ print("Error: debug got %d kernel events insteads of 0" % (dbg)) + elif ok == 1: +- print "OK" ++ print("OK") + + shutil.rmtree ("/media/test/a", True) +--- a/py-compile 2020-04-28 10:09:56.813551018 +0300 ++++ b/py-compile 2020-04-28 12:05:58.349373709 +0300 +@@ -107,34 +107,34 @@ + + files = '''$files''' + +-print 'Byte-compiling python modules...' +-for file in string.split(files): ++print('Byte-compiling python modules...') ++for file in str(files).split(): + $pathtrans + $filetrans + if not os.path.exists(filepath) or not (len(filepath) >= 3 + and filepath[-3:] == '.py'): +- continue +- print file, +- sys.stdout.flush() ++ continue ++ print(file, ++ sys.stdout.flush()) + py_compile.compile(filepath, filepath + 'c', path) +-print" || exit $? ++print()" || exit $? + + # this will fail for python < 1.5, but that doesn't matter ... + $PYTHON -O -c " + import sys, os, string, py_compile + + files = '''$files''' +-print 'Byte-compiling python modules (optimized versions) ...' +-for file in string.split(files): ++print('Byte-compiling python modules (optimized versions) ...') ++for file in str(files).split(): + $pathtrans + $filetrans + if not os.path.exists(filepath) or not (len(filepath) >= 3 + and filepath[-3:] == '.py'): +- continue +- print file, +- sys.stdout.flush() ++ continue ++ print(file, ++ sys.stdout.flush()) + py_compile.compile(filepath, filepath + 'o', path) +-print" 2>/dev/null || : ++print()" 2>/dev/null || : + + # Local Variables: + # mode: shell-script +--- a/python/gamin.py 2020-04-28 11:32:25.005794146 +0300 ++++ b/python/gamin.py 2020-04-28 12:41:56.560517035 +0300 +@@ -4,7 +4,7 @@ + import os.path + + has_debug_api = 0 +-if _gamin.__dict__.has_key("MonitorDebug"): ++if "MonitorDebug" in _gamin.__dict__: + has_debug_api = 1 + + # +@@ -36,7 +36,7 @@ + + def GaminErrmsg(err = None): + if err == None: +- err = _gamin.Errno() ++ err = _gamin.Errno() + if err == GAM_ARG: + msg = "bad argument error" + elif err == GAM_FILE: +@@ -58,12 +58,12 @@ + class GaminException(Exception): + def __init__(self, value): + Exception.__init__(self) +- self.value = value +- self.errno = GaminErrno() ++ self.value = value ++ self.errno = GaminErrno() + + def __str__(self): + str = GaminErrmsg(self.errno) +- if str != "": ++ if str != "": + return repr(self.value) + ': ' + str + return repr(self.value) + +@@ -76,181 +76,181 @@ + FAM API events.""" + + class WatchObject: +- def __init__ (self, monitor, mon_no, path, dir, callback, data=None): +- self.monitor = monitor +- self.callback = callback +- self.data = data +- self.path = path +- self.__mon_no = mon_no +- if dir == 1: +- ret = _gamin.MonitorDirectory(self.__mon_no, path, self); +- if ret < 0: +- raise(GaminException("Failed to monitor directory %s" % +- (path))) +- elif dir == 0: +- ret = _gamin.MonitorFile(self.__mon_no, path, self); +- if ret < 0: +- raise(GaminException("Failed to monitor file %s" % +- (path))) +- elif dir == -1: +- ret = _gamin.MonitorDebug(self.__mon_no, path, self); +- if ret < 0: +- raise(GaminException("Failed to debug %s" % +- (path))) +- self.__req_no = ret +- +- def _internal_callback(self, path, event): +- # it is very important here to catch all exception which may +- # arise in the client callback code. +- try: +- if self.data != None: +- self.callback (path, event, self.data) +- else: +- self.callback (path, event) +- except: +- import traceback +- traceback.print_exc() +- +- if event == GAMAcknowledge: +- try: +- self.monitor.cancelled.remove(self) +- except: +- print "gamin failed to remove from cancelled" +- pass +- +- def cancel(self): +- ret = _gamin.MonitorCancel(self.__mon_no, self.__req_no); +- if ret < 0: +- raise(GaminException("Failed to stop monitor on %s" % +- (self.path))) +- try: +- self.monitor.cancelled.append(self) +- except: +- print "gamin cancel() failed to add to cancelled" ++ def __init__ (self, monitor, mon_no, path, dir, callback, data=None): ++ self.monitor = monitor ++ self.callback = callback ++ self.data = data ++ self.path = path ++ self.__mon_no = mon_no ++ if dir == 1: ++ ret = _gamin.MonitorDirectory(self.__mon_no, path, self); ++ if ret < 0: ++ raise(GaminException("Failed to monitor directory %s" % ++ (path))) ++ elif dir == 0: ++ ret = _gamin.MonitorFile(self.__mon_no, path, self); ++ if ret < 0: ++ raise(GaminException("Failed to monitor file %s" % ++ (path))) ++ elif dir == -1: ++ ret = _gamin.MonitorDebug(self.__mon_no, path, self); ++ if ret < 0: ++ raise(GaminException("Failed to debug %s" % ++ (path))) ++ self.__req_no = ret ++ ++ def _internal_callback(self, path, event): ++ # it is very important here to catch all exception which may ++ # arise in the client callback code. ++ try: ++ if self.data != None: ++ self.callback (path, event, self.data) ++ else: ++ self.callback (path, event) ++ except: ++ import traceback ++ traceback.print_exc() ++ ++ if event == GAMAcknowledge: ++ try: ++ self.monitor.cancelled.remove(self) ++ except: ++ print("gamin failed to remove from cancelled") ++ pass ++ ++ def cancel(self): ++ ret = _gamin.MonitorCancel(self.__mon_no, self.__req_no); ++ if ret < 0: ++ raise(GaminException("Failed to stop monitor on %s" % ++ (self.path))) ++ try: ++ self.monitor.cancelled.append(self) ++ except: ++ print("gamin cancel() failed to add to cancelled") + + def __init__ (self): + self.__no = _gamin.MonitorConnect() +- if self.__no < 0: +- raise(GaminException("Failed to connect to gam_server")) +- self.objects = {} +- self.__fd = _gamin.GetFd(self.__no) +- if self.__fd < 0: +- _gamin.MonitorClose(self.__no) +- raise(GaminException("Failed to get file descriptor")) +- self.cancelled = [] ++ if self.__no < 0: ++ raise(GaminException("Failed to connect to gam_server")) ++ self.objects = {} ++ self.__fd = _gamin.GetFd(self.__no) ++ if self.__fd < 0: ++ _gamin.MonitorClose(self.__no) ++ raise(GaminException("Failed to get file descriptor")) ++ self.cancelled = [] + + def __del__ (self): + self.disconnect() + + def __raise_disconnected(): +- raise(GaminException("Already disconnected")) ++ raise(GaminException("Already disconnected")) + + def _debug_object(self, value, callback, data = None): + if has_debug_api == 0: +- return; ++ return; + + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + obj = self.WatchObject(self, self.__no, value, -1, callback, data) +- # persistency need to be insured +- self.objects["debug"] = obj +- return obj ++ # persistency need to be insured ++ self.objects["debug"] = obj ++ return obj + + def disconnect(self): + if (self.__no >= 0): +- _gamin.MonitorClose(self.__no) +- self.__no = -1; ++ _gamin.MonitorClose(self.__no) ++ self.__no = -1; + + def watch_directory(self, directory, callback, data = None): + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + directory = os.path.abspath(directory) + + obj = self.WatchObject(self, self.__no, directory, 1, callback, data) +- if self.objects.has_key(directory): +- self.objects[directory].append(obj) +- else: +- self.objects[directory] = [obj] +- return obj ++ if directory in self.objects: ++ self.objects[directory].append(obj) ++ else: ++ self.objects[directory] = [obj] ++ return obj + + def watch_file(self, file, callback, data = None): + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + file = os.path.abspath(file) + + obj = self.WatchObject(self, self.__no, file, 0, callback, data) +- if self.objects.has_key(file): +- self.objects[file].append(obj) +- else: +- self.objects[file] = [obj] +- return obj ++ if file in self.objects: ++ self.objects[file].append(obj) ++ else: ++ self.objects[file] = [obj] ++ return obj + + def no_exists(self): + if (self.__no < 0): +- return +- ret = _gamin.MonitorNoExists(self.__no) +- return ret ++ return ++ ret = _gamin.MonitorNoExists(self.__no) ++ return ret + + def stop_watch(self, path): + if (self.__no < 0): +- return ++ return + path = os.path.abspath(path) +- try: +- list = self.objects[path] +- except: +- raise(GaminException("Resource %s is not monitored" % (path))) +- for obj in list: +- obj.cancel() +- self.objects[path] = [] +- ++ try: ++ list = self.objects[path] ++ except: ++ raise(GaminException("Resource %s is not monitored" % (path))) ++ for obj in list: ++ obj.cancel() ++ self.objects[path] = [] ++ + def get_fd(self): + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + return self.__fd + + def event_pending(self): + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + ret = _gamin.EventPending(self.__no); +- if ret < 0: +- raise(GaminException("Failed to check pending events")) +- return ret ++ if ret < 0: ++ raise(GaminException("Failed to check pending events")) ++ return ret + + def handle_one_event(self): + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + ret = _gamin.ProcessOneEvent(self.__no); +- if ret < 0: +- raise(GaminException("Failed to process one event")) +- return ret ++ if ret < 0: ++ raise(GaminException("Failed to process one event")) ++ return ret + + def handle_events(self): + if (self.__no < 0): +- self.__raise_disconnected(); ++ self.__raise_disconnected(); + ret = _gamin.ProcessEvents(self.__no); +- if ret < 0: +- raise(GaminException("Failed to process events")) +- return ret ++ if ret < 0: ++ raise(GaminException("Failed to process events")) ++ return ret + + def run_unit_tests(): + def callback(path, event): +- print "Got callback: %s, %s" % (path, event) ++ print("Got callback: %s, %s" % (path, event)) + mon = WatchMonitor() +- print "watching current directory" ++ print("watching current directory") + mon.watch_directory(".", callback) + import time + time.sleep(1) +- print "fd: ", mon.get_fd() ++ print("fd: ", mon.get_fd()) + ret = mon.event_pending() +- print "pending: ", ret ++ print("pending: ", ret) + if ret > 0: + ret = mon.handle_one_event() +- print "processed %d event" % (ret) +- ret = mon.handle_events() +- print "processed %d remaining events" % (ret) +- print "stop watching current directory" ++ print("processed %d event" % (ret)) ++ ret = mon.handle_events() ++ print("processed %d remaining events" % (ret)) ++ print("stop watching current directory") + mon.stop_watch(".") +- print "disconnecting" ++ print("disconnecting") + del mon + + if __name__ == '__main__': +--- a/gamin.spec.in 2020-04-28 11:39:33.414597930 +0300 ++++ b/gamin.spec.in 2020-04-28 11:40:33.141565854 +0300 +@@ -32,7 +32,7 @@ + Summary: Python bindings for the gamin library + Group: Development/Libraries + Requires: gamin = %{version} +-Requires: %{_libdir}/python%(echo `python -c "import sys; print sys.version[0:3]"`) ++Requires: %{_libdir}/python%(echo `python -c "import sys; print(sys.version[0:3])"`) + + %description python + The gamin-python package contains a module that allow monitoring of +--- a/doc/apibuild.py 2020-04-28 11:39:54.804705751 +0300 ++++ b/doc/apibuild.py 2020-04-28 11:46:21.249997412 +0300 +@@ -47,33 +47,33 @@ + def __init__(self, name, module=None, type=None, lineno = 0, + info=None, extra=None, conditionals = None): + self.name = name +- self.module = module +- self.type = type +- self.info = info +- self.extra = extra +- self.lineno = lineno +- self.static = 0 +- if conditionals == None or len(conditionals) == 0: +- self.conditionals = None +- else: +- self.conditionals = conditionals[:] +- if self.name == debugsym: +- print "=> define %s : %s" % (debugsym, (module, type, info, +- extra, conditionals)) ++ self.module = module ++ self.type = type ++ self.info = info ++ self.extra = extra ++ self.lineno = lineno ++ self.static = 0 ++ if conditionals == None or len(conditionals) == 0: ++ self.conditionals = None ++ else: ++ self.conditionals = conditionals[:] ++ if self.name == debugsym: ++ print("=> define %s : %s" % (debugsym, (module, type, info, ++ extra, conditionals))) + + def __repr__(self): + r = "%s %s:" % (self.type, self.name) +- if self.static: +- r = r + " static" +- if self.module != None: +- r = r + " from %s" % (self.module) +- if self.info != None: +- r = r + " " + `self.info` +- if self.extra != None: +- r = r + " " + `self.extra` +- if self.conditionals != None: +- r = r + " " + `self.conditionals` +- return r ++ if self.static: ++ r = r + " static" ++ if self.module != None: ++ r = r + " from %s" % (self.module) ++ if self.info != None: ++ r = r + " " + self.info ++ if self.extra != None: ++ r = r + " " + self.extra ++ if self.conditionals != None: ++ r = r + " " + self.conditionals ++ return r + + + def set_module(self, module): +@@ -89,10 +89,10 @@ + def set_static(self, static): + self.static = static + def set_conditionals(self, conditionals): +- if conditionals == None or len(conditionals) == 0: +- self.conditionals = None +- else: +- self.conditionals = conditionals[:] ++ if conditionals == None or len(conditionals) == 0: ++ self.conditionals = None ++ else: ++ self.conditionals = conditionals[:] + + def get_name(self): + return self.name +@@ -113,19 +113,19 @@ + + def update(self, module, type = None, info = None, extra=None, + conditionals=None): +- if self.name == debugsym: +- print "=> update %s : %s" % (debugsym, (module, type, info, +- extra, conditionals)) ++ if self.name == debugsym: ++ print("=> update %s : %s" % (debugsym, (module, type, info, ++ extra, conditionals))) + if module != None and self.module == None: +- self.set_module(module) ++ self.set_module(module) + if type != None and self.type == None: +- self.set_type(type) ++ self.set_type(type) + if info != None: +- self.set_info(info) ++ self.set_info(info) + if extra != None: +- self.set_extra(extra) ++ self.set_extra(extra) + if conditionals != None: +- self.set_conditionals(conditionals) ++ self.set_conditionals(conditionals) + + + class index: +@@ -133,75 +133,75 @@ + self.name = name + self.identifiers = {} + self.functions = {} +- self.variables = {} +- self.includes = {} +- self.structs = {} +- self.enums = {} +- self.typedefs = {} +- self.macros = {} +- self.references = {} +- self.info = {} ++ self.variables = {} ++ self.includes = {} ++ self.structs = {} ++ self.enums = {} ++ self.typedefs = {} ++ self.macros = {} ++ self.references = {} ++ self.info = {} + + def add_ref(self, name, module, static, type, lineno, info=None, extra=None, conditionals = None): + if name[0:2] == '__': +- return None ++ return None + d = None + try: +- d = self.identifiers[name] +- d.update(module, type, lineno, info, extra, conditionals) +- except: +- d = identifier(name, module, type, lineno, info, extra, conditionals) +- self.identifiers[name] = d +- +- if d != None and static == 1: +- d.set_static(1) ++ d = self.identifiers[name] ++ d.update(module, type, lineno, info, extra, conditionals) ++ except: ++ d = identifier(name, module, type, lineno, info, extra, conditionals) ++ self.identifiers[name] = d ++ ++ if d != None and static == 1: ++ d.set_static(1) + +- if d != None and name != None and type != None: +- self.references[name] = d ++ if d != None and name != None and type != None: ++ self.references[name] = d + +- if name == debugsym: +- print "New ref: %s" % (d) ++ if name == debugsym: ++ print("New ref: %s" % (d)) + +- return d ++ return d + + def add(self, name, module, static, type, lineno, info=None, extra=None, conditionals = None): + if name[0:2] == '__': +- return None ++ return None + d = None + try: +- d = self.identifiers[name] +- d.update(module, type, lineno, info, extra, conditionals) +- except: +- d = identifier(name, module, type, lineno, info, extra, conditionals) +- self.identifiers[name] = d +- +- if d != None and static == 1: +- d.set_static(1) +- +- if d != None and name != None and type != None: +- if type == "function": +- self.functions[name] = d +- elif type == "functype": +- self.functions[name] = d +- elif type == "variable": +- self.variables[name] = d +- elif type == "include": +- self.includes[name] = d +- elif type == "struct": +- self.structs[name] = d +- elif type == "enum": +- self.enums[name] = d +- elif type == "typedef": +- self.typedefs[name] = d +- elif type == "macro": +- self.macros[name] = d +- else: +- print "Unable to register type ", type ++ d = self.identifiers[name] ++ d.update(module, type, lineno, info, extra, conditionals) ++ except: ++ d = identifier(name, module, type, lineno, info, extra, conditionals) ++ self.identifiers[name] = d ++ ++ if d != None and static == 1: ++ d.set_static(1) ++ ++ if d != None and name != None and type != None: ++ if type == "function": ++ self.functions[name] = d ++ elif type == "functype": ++ self.functions[name] = d ++ elif type == "variable": ++ self.variables[name] = d ++ elif type == "include": ++ self.includes[name] = d ++ elif type == "struct": ++ self.structs[name] = d ++ elif type == "enum": ++ self.enums[name] = d ++ elif type == "typedef": ++ self.typedefs[name] = d ++ elif type == "macro": ++ self.macros[name] = d ++ else: ++ print("Unable to register type ", type) + +- if name == debugsym: +- print "New symbol: %s" % (d) ++ if name == debugsym: ++ print("New symbol: %s" % (d)) + +- return d ++ return d + + def merge(self, idx): + for id in idx.functions.keys(): +@@ -209,41 +209,41 @@ + # macro might be used to override functions or variables + # definitions + # +- if self.macros.has_key(id): +- del self.macros[id] +- if self.functions.has_key(id): +- print "function %s from %s redeclared in %s" % ( +- id, self.functions[id].module, idx.functions[id].module) +- else: +- self.functions[id] = idx.functions[id] +- self.identifiers[id] = idx.functions[id] ++ if self.macros.has_key(id): ++ del self.macros[id] ++ if self.functions.has_key(id): ++ print("function %s from %s redeclared in %s" % ( ++ id, self.functions[id].module, idx.functions[id].module)) ++ else: ++ self.functions[id] = idx.functions[id] ++ self.identifiers[id] = idx.functions[id] + for id in idx.variables.keys(): + # + # macro might be used to override functions or variables + # definitions + # +- if self.macros.has_key(id): +- del self.macros[id] +- if self.variables.has_key(id): +- print "variable %s from %s redeclared in %s" % ( +- id, self.variables[id].module, idx.variables[id].module) +- else: +- self.variables[id] = idx.variables[id] +- self.identifiers[id] = idx.variables[id] ++ if self.macros.has_key(id): ++ del self.macros[id] ++ if self.variables.has_key(id): ++ print("variable %s from %s redeclared in %s" % ( ++ id, self.variables[id].module, idx.variables[id].module)) ++ else: ++ self.variables[id] = idx.variables[id] ++ self.identifiers[id] = idx.variables[id] + for id in idx.structs.keys(): +- if self.structs.has_key(id): +- print "struct %s from %s redeclared in %s" % ( +- id, self.structs[id].module, idx.structs[id].module) +- else: +- self.structs[id] = idx.structs[id] +- self.identifiers[id] = idx.structs[id] ++ if self.structs.has_key(id): ++ print("struct %s from %s redeclared in %s" % ( ++ id, self.structs[id].module, idx.structs[id].module)) ++ else: ++ self.structs[id] = idx.structs[id] ++ self.identifiers[id] = idx.structs[id] + for id in idx.typedefs.keys(): +- if self.typedefs.has_key(id): +- print "typedef %s from %s redeclared in %s" % ( +- id, self.typedefs[id].module, idx.typedefs[id].module) +- else: +- self.typedefs[id] = idx.typedefs[id] +- self.identifiers[id] = idx.typedefs[id] ++ if self.typedefs.has_key(id): ++ print("typedef %s from %s redeclared in %s" % ( ++ id, self.typedefs[id].module, idx.typedefs[id].module)) ++ else: ++ self.typedefs[id] = idx.typedefs[id] ++ self.identifiers[id] = idx.typedefs[id] + for id in idx.macros.keys(): + # + # macro might be used to override functions or variables +@@ -255,83 +255,83 @@ + continue + if self.enums.has_key(id): + continue +- if self.macros.has_key(id): +- print "macro %s from %s redeclared in %s" % ( +- id, self.macros[id].module, idx.macros[id].module) +- else: +- self.macros[id] = idx.macros[id] +- self.identifiers[id] = idx.macros[id] ++ if self.macros.has_key(id): ++ print("macro %s from %s redeclared in %s" % ( ++ id, self.macros[id].module, idx.macros[id].module)) ++ else: ++ self.macros[id] = idx.macros[id] ++ self.identifiers[id] = idx.macros[id] + for id in idx.enums.keys(): +- if self.enums.has_key(id): +- print "enum %s from %s redeclared in %s" % ( +- id, self.enums[id].module, idx.enums[id].module) +- else: +- self.enums[id] = idx.enums[id] +- self.identifiers[id] = idx.enums[id] ++ if self.enums.has_key(id): ++ print("enum %s from %s redeclared in %s" % ( ++ id, self.enums[id].module, idx.enums[id].module)) ++ else: ++ self.enums[id] = idx.enums[id] ++ self.identifiers[id] = idx.enums[id] + + def merge_public(self, idx): + for id in idx.functions.keys(): +- if self.functions.has_key(id): +- up = idx.functions[id] +- self.functions[id].update(None, up.type, up.info, up.extra) +- # else: +- # print "Function %s from %s is not declared in headers" % ( +- # id, idx.functions[id].module) +- # TODO: do the same for variables. ++ if self.functions.has_key(id): ++ up = idx.functions[id] ++ self.functions[id].update(None, up.type, up.info, up.extra) ++ # else: ++ # print("Function %s from %s is not declared in headers" % ( ++ # id, idx.functions[id].module)) ++ # TODO: do the same for variables. + + def analyze_dict(self, type, dict): + count = 0 +- public = 0 ++ public = 0 + for name in dict.keys(): +- id = dict[name] +- count = count + 1 +- if id.static == 0: +- public = public + 1 ++ id = dict[name] ++ count = count + 1 ++ if id.static == 0: ++ public = public + 1 + if count != public: +- print " %d %s , %d public" % (count, type, public) +- elif count != 0: +- print " %d public %s" % (count, type) ++ print(" %d %s , %d public" % (count, type, public)) ++ elif count != 0: ++ print(" %d public %s" % (count, type)) + + + def analyze(self): +- self.analyze_dict("functions", self.functions) +- self.analyze_dict("variables", self.variables) +- self.analyze_dict("structs", self.structs) +- self.analyze_dict("typedefs", self.typedefs) +- self.analyze_dict("macros", self.macros) ++ self.analyze_dict("functions", self.functions) ++ self.analyze_dict("variables", self.variables) ++ self.analyze_dict("structs", self.structs) ++ self.analyze_dict("typedefs", self.typedefs) ++ self.analyze_dict("macros", self.macros) + + class CLexer: + """A lexer for the C language, tokenize the input by reading and + analyzing it line by line""" + def __init__(self, input): + self.input = input +- self.tokens = [] +- self.line = "" +- self.lineno = 0 ++ self.tokens = [] ++ self.line = "" ++ self.lineno = 0 + + def getline(self): + line = '' +- while line == '': +- line = self.input.readline() +- if not line: +- return None +- self.lineno = self.lineno + 1 +- line = string.lstrip(line) +- line = string.rstrip(line) +- if line == '': +- continue +- while line[-1] == '\\': +- line = line[:-1] +- n = self.input.readline() +- self.lineno = self.lineno + 1 +- n = string.lstrip(n) +- n = string.rstrip(n) +- if not n: +- break +- else: +- line = line + n ++ while line == '': ++ line = self.input.readline() ++ if not line: ++ return None ++ self.lineno = self.lineno + 1 ++ line = string.lstrip(line) ++ line = string.rstrip(line) ++ if line == '': ++ continue ++ while line[-1] == '\\': ++ line = line[:-1] ++ n = self.input.readline() ++ self.lineno = self.lineno + 1 ++ n = string.lstrip(n) ++ n = string.rstrip(n) ++ if not n: ++ break ++ else: ++ line = line + n + return line +- ++ + def getlineno(self): + return self.lineno + +@@ -339,194 +339,194 @@ + self.tokens.insert(0, token); + + def debug(self): +- print "Last token: ", self.last +- print "Token queue: ", self.tokens +- print "Line %d end: " % (self.lineno), self.line ++ print("Last token: ", self.last) ++ print("Token queue: ", self.tokens) ++ print("Line %d end: " % (self.lineno), self.line) + + def token(self): + while self.tokens == []: +- if self.line == "": +- line = self.getline() +- else: +- line = self.line +- self.line = "" +- if line == None: +- return None +- +- if line[0] == '#': +- self.tokens = map((lambda x: ('preproc', x)), +- string.split(line)) +- break; +- l = len(line) +- if line[0] == '"' or line[0] == "'": +- end = line[0] +- line = line[1:] +- found = 0 +- tok = "" +- while found == 0: +- i = 0 +- l = len(line) +- while i < l: +- if line[i] == end: +- self.line = line[i+1:] +- line = line[:i] +- l = i +- found = 1 +- break +- if line[i] == '\\': +- i = i + 1 +- i = i + 1 +- tok = tok + line +- if found == 0: +- line = self.getline() +- if line == None: +- return None +- self.last = ('string', tok) +- return self.last +- +- if l >= 2 and line[0] == '/' and line[1] == '*': +- line = line[2:] +- found = 0 +- tok = "" +- while found == 0: +- i = 0 +- l = len(line) +- while i < l: +- if line[i] == '*' and i+1 < l and line[i+1] == '/': +- self.line = line[i+2:] +- line = line[:i-1] +- l = i +- found = 1 +- break +- i = i + 1 +- if tok != "": +- tok = tok + "\n" +- tok = tok + line +- if found == 0: +- line = self.getline() +- if line == None: +- return None +- self.last = ('comment', tok) +- return self.last +- if l >= 2 and line[0] == '/' and line[1] == '/': +- line = line[2:] +- self.last = ('comment', line) +- return self.last +- i = 0 +- while i < l: +- if line[i] == '/' and i+1 < l and line[i+1] == '/': +- self.line = line[i:] +- line = line[:i] +- break +- if line[i] == '/' and i+1 < l and line[i+1] == '*': +- self.line = line[i:] +- line = line[:i] +- break +- if line[i] == '"' or line[i] == "'": +- self.line = line[i:] +- line = line[:i] +- break +- i = i + 1 +- l = len(line) +- i = 0 +- while i < l: +- if line[i] == ' ' or line[i] == '\t': +- i = i + 1 +- continue +- o = ord(line[i]) +- if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ +- (o >= 48 and o <= 57): +- s = i +- while i < l: +- o = ord(line[i]) +- if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ +- (o >= 48 and o <= 57) or string.find( +- " \t(){}:;,+-*/%&!|[]=><", line[i]) == -1: +- i = i + 1 +- else: +- break +- self.tokens.append(('name', line[s:i])) +- continue +- if string.find("(){}:;,[]", line[i]) != -1: ++ if self.line == "": ++ line = self.getline() ++ else: ++ line = self.line ++ self.line = "" ++ if line == None: ++ return None ++ ++ if line[0] == '#': ++ self.tokens = map((lambda x: ('preproc', x)), ++ string.split(line)) ++ break; ++ l = len(line) ++ if line[0] == '"' or line[0] == "'": ++ end = line[0] ++ line = line[1:] ++ found = 0 ++ tok = "" ++ while found == 0: ++ i = 0 ++ l = len(line) ++ while i < l: ++ if line[i] == end: ++ self.line = line[i+1:] ++ line = line[:i] ++ l = i ++ found = 1 ++ break ++ if line[i] == '\\': ++ i = i + 1 ++ i = i + 1 ++ tok = tok + line ++ if found == 0: ++ line = self.getline() ++ if line == None: ++ return None ++ self.last = ('string', tok) ++ return self.last ++ ++ if l >= 2 and line[0] == '/' and line[1] == '*': ++ line = line[2:] ++ found = 0 ++ tok = "" ++ while found == 0: ++ i = 0 ++ l = len(line) ++ while i < l: ++ if line[i] == '*' and i+1 < l and line[i+1] == '/': ++ self.line = line[i+2:] ++ line = line[:i-1] ++ l = i ++ found = 1 ++ break ++ i = i + 1 ++ if tok != "": ++ tok = tok + "\n" ++ tok = tok + line ++ if found == 0: ++ line = self.getline() ++ if line == None: ++ return None ++ self.last = ('comment', tok) ++ return self.last ++ if l >= 2 and line[0] == '/' and line[1] == '/': ++ line = line[2:] ++ self.last = ('comment', line) ++ return self.last ++ i = 0 ++ while i < l: ++ if line[i] == '/' and i+1 < l and line[i+1] == '/': ++ self.line = line[i:] ++ line = line[:i] ++ break ++ if line[i] == '/' and i+1 < l and line[i+1] == '*': ++ self.line = line[i:] ++ line = line[:i] ++ break ++ if line[i] == '"' or line[i] == "'": ++ self.line = line[i:] ++ line = line[:i] ++ break ++ i = i + 1 ++ l = len(line) ++ i = 0 ++ while i < l: ++ if line[i] == ' ' or line[i] == '\t': ++ i = i + 1 ++ continue ++ o = ord(line[i]) ++ if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ ++ (o >= 48 and o <= 57): ++ s = i ++ while i < l: ++ o = ord(line[i]) ++ if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ ++ (o >= 48 and o <= 57) or string.find( ++ " \t(){}:;,+-*/%&!|[]=><", line[i]) == -1: ++ i = i + 1 ++ else: ++ break ++ self.tokens.append(('name', line[s:i])) ++ continue ++ if string.find("(){}:;,[]", line[i]) != -1: + # if line[i] == '(' or line[i] == ')' or line[i] == '{' or \ +-# line[i] == '}' or line[i] == ':' or line[i] == ';' or \ +-# line[i] == ',' or line[i] == '[' or line[i] == ']': +- self.tokens.append(('sep', line[i])) +- i = i + 1 +- continue +- if string.find("+-*><=/%&!|.", line[i]) != -1: ++# line[i] == '}' or line[i] == ':' or line[i] == ';' or \ ++# line[i] == ',' or line[i] == '[' or line[i] == ']': ++ self.tokens.append(('sep', line[i])) ++ i = i + 1 ++ continue ++ if string.find("+-*><=/%&!|.", line[i]) != -1: + # if line[i] == '+' or line[i] == '-' or line[i] == '*' or \ +-# line[i] == '>' or line[i] == '<' or line[i] == '=' or \ +-# line[i] == '/' or line[i] == '%' or line[i] == '&' or \ +-# line[i] == '!' or line[i] == '|' or line[i] == '.': +- if line[i] == '.' and i + 2 < l and \ +- line[i+1] == '.' and line[i+2] == '.': +- self.tokens.append(('name', '...')) +- i = i + 3 +- continue +- +- j = i + 1 +- if j < l and ( +- string.find("+-*><=/%&!|", line[j]) != -1): +-# line[j] == '+' or line[j] == '-' or line[j] == '*' or \ +-# line[j] == '>' or line[j] == '<' or line[j] == '=' or \ +-# line[j] == '/' or line[j] == '%' or line[j] == '&' or \ +-# line[j] == '!' or line[j] == '|'): +- self.tokens.append(('op', line[i:j+1])) +- i = j + 1 +- else: +- self.tokens.append(('op', line[i])) +- i = i + 1 +- continue +- s = i +- while i < l: +- o = ord(line[i]) +- if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ +- (o >= 48 and o <= 57) or ( +- string.find(" \t(){}:;,+-*/%&!|[]=><", line[i]) == -1): +-# line[i] != ' ' and line[i] != '\t' and +-# line[i] != '(' and line[i] != ')' and +-# line[i] != '{' and line[i] != '}' and +-# line[i] != ':' and line[i] != ';' and +-# line[i] != ',' and line[i] != '+' and +-# line[i] != '-' and line[i] != '*' and +-# line[i] != '/' and line[i] != '%' and +-# line[i] != '&' and line[i] != '!' and +-# line[i] != '|' and line[i] != '[' and +-# line[i] != ']' and line[i] != '=' and +-# line[i] != '*' and line[i] != '>' and +-# line[i] != '<'): +- i = i + 1 +- else: +- break +- self.tokens.append(('name', line[s:i])) ++# line[i] == '>' or line[i] == '<' or line[i] == '=' or \ ++# line[i] == '/' or line[i] == '%' or line[i] == '&' or \ ++# line[i] == '!' or line[i] == '|' or line[i] == '.': ++ if line[i] == '.' and i + 2 < l and \ ++ line[i+1] == '.' and line[i+2] == '.': ++ self.tokens.append(('name', '...')) ++ i = i + 3 ++ continue ++ ++ j = i + 1 ++ if j < l and ( ++ string.find("+-*><=/%&!|", line[j]) != -1): ++# line[j] == '+' or line[j] == '-' or line[j] == '*' or \ ++# line[j] == '>' or line[j] == '<' or line[j] == '=' or \ ++# line[j] == '/' or line[j] == '%' or line[j] == '&' or \ ++# line[j] == '!' or line[j] == '|'): ++ self.tokens.append(('op', line[i:j+1])) ++ i = j + 1 ++ else: ++ self.tokens.append(('op', line[i])) ++ i = i + 1 ++ continue ++ s = i ++ while i < l: ++ o = ord(line[i]) ++ if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ ++ (o >= 48 and o <= 57) or ( ++ string.find(" \t(){}:;,+-*/%&!|[]=><", line[i]) == -1): ++# line[i] != ' ' and line[i] != '\t' and ++# line[i] != '(' and line[i] != ')' and ++# line[i] != '{' and line[i] != '}' and ++# line[i] != ':' and line[i] != ';' and ++# line[i] != ',' and line[i] != '+' and ++# line[i] != '-' and line[i] != '*' and ++# line[i] != '/' and line[i] != '%' and ++# line[i] != '&' and line[i] != '!' and ++# line[i] != '|' and line[i] != '[' and ++# line[i] != ']' and line[i] != '=' and ++# line[i] != '*' and line[i] != '>' and ++# line[i] != '<'): ++ i = i + 1 ++ else: ++ break ++ self.tokens.append(('name', line[s:i])) + +- tok = self.tokens[0] +- self.tokens = self.tokens[1:] +- self.last = tok +- return tok ++ tok = self.tokens[0] ++ self.tokens = self.tokens[1:] ++ self.last = tok ++ return tok + + class CParser: + """The C module parser""" + def __init__(self, filename, idx = None): + self.filename = filename +- if len(filename) > 2 and filename[-2:] == '.h': +- self.is_header = 1 +- else: +- self.is_header = 0 ++ if len(filename) > 2 and filename[-2:] == '.h': ++ self.is_header = 1 ++ else: ++ self.is_header = 0 + self.input = open(filename) +- self.lexer = CLexer(self.input) +- if idx == None: +- self.index = index() +- else: +- self.index = idx +- self.top_comment = "" +- self.last_comment = "" +- self.comment = None +- self.collect_ref = 0 +- self.no_error = 0 +- self.conditionals = [] +- self.defines = [] ++ self.lexer = CLexer(self.input) ++ if idx == None: ++ self.index = index() ++ else: ++ self.index = idx ++ self.top_comment = "" ++ self.last_comment = "" ++ self.comment = None ++ self.collect_ref = 0 ++ self.no_error = 0 ++ self.conditionals = [] ++ self.defines = [] + + def collect_references(self): + self.collect_ref = 1 +@@ -542,149 +542,149 @@ + + def index_add(self, name, module, static, type, info=None, extra = None): + self.index.add(name, module, static, type, self.lineno(), +- info, extra, self.conditionals) ++ info, extra, self.conditionals) + + def index_add_ref(self, name, module, static, type, info=None, + extra = None): + self.index.add_ref(name, module, static, type, self.lineno(), +- info, extra, self.conditionals) ++ info, extra, self.conditionals) + + def warning(self, msg): + if self.no_error: +- return +- print msg ++ return ++ print(msg) + + def error(self, msg, token=-1): + if self.no_error: +- return ++ return + +- print "Parse Error: " + msg +- if token != -1: +- print "Got token ", token +- self.lexer.debug() +- sys.exit(1) ++ print("Parse Error: " + msg) ++ if token != -1: ++ print("Got token ", token) ++ self.lexer.debug() ++ sys.exit(1) + + def debug(self, msg, token=-1): +- print "Debug: " + msg +- if token != -1: +- print "Got token ", token +- self.lexer.debug() ++ print("Debug: " + msg) ++ if token != -1: ++ print("Got token ", token) ++ self.lexer.debug() + + def parseTopComment(self, comment): +- res = {} +- lines = string.split(comment, "\n") +- item = None +- for line in lines: +- while line != "" and (line[0] == ' ' or line[0] == '\t'): +- line = line[1:] +- while line != "" and line[0] == '*': +- line = line[1:] +- while line != "" and (line[0] == ' ' or line[0] == '\t'): +- line = line[1:] +- try: +- (it, line) = string.split(line, ":", 1) +- item = it +- while line != "" and (line[0] == ' ' or line[0] == '\t'): +- line = line[1:] +- if res.has_key(item): +- res[item] = res[item] + " " + line +- else: +- res[item] = line +- except: +- if item != None: +- if res.has_key(item): +- res[item] = res[item] + " " + line +- else: +- res[item] = line +- self.index.info = res ++ res = {} ++ lines = string.split(comment, "\n") ++ item = None ++ for line in lines: ++ while line != "" and (line[0] == ' ' or line[0] == '\t'): ++ line = line[1:] ++ while line != "" and line[0] == '*': ++ line = line[1:] ++ while line != "" and (line[0] == ' ' or line[0] == '\t'): ++ line = line[1:] ++ try: ++ (it, line) = string.split(line, ":", 1) ++ item = it ++ while line != "" and (line[0] == ' ' or line[0] == '\t'): ++ line = line[1:] ++ if res.has_key(item): ++ res[item] = res[item] + " " + line ++ else: ++ res[item] = line ++ except: ++ if item != None: ++ if res.has_key(item): ++ res[item] = res[item] + " " + line ++ else: ++ res[item] = line ++ self.index.info = res + + def parseComment(self, token): + if self.top_comment == "": +- self.top_comment = token[1] +- if self.comment == None or token[1][0] == '*': +- self.comment = token[1]; +- else: +- self.comment = self.comment + token[1] +- token = self.lexer.token() ++ self.top_comment = token[1] ++ if self.comment == None or token[1][0] == '*': ++ self.comment = token[1]; ++ else: ++ self.comment = self.comment + token[1] ++ token = self.lexer.token() + + if string.find(self.comment, "DOC_DISABLE") != -1: +- self.stop_error() ++ self.stop_error() + + if string.find(self.comment, "DOC_ENABLE") != -1: +- self.start_error() ++ self.start_error() + +- return token ++ return token + + # + # Parse a comment block associate to a macro + # + def parseMacroComment(self, name, quiet = 0): + if name[0:2] == '__': +- quiet = 1 ++ quiet = 1 + + args = [] +- desc = "" ++ desc = "" + + if self.comment == None: +- if not quiet: +- self.warning("Missing comment for macro %s" % (name)) +- return((args, desc)) ++ if not quiet: ++ self.warning("Missing comment for macro %s" % (name)) ++ return((args, desc)) + if self.comment[0] != '*': +- if not quiet: +- self.warning("Missing * in macro comment for %s" % (name)) +- return((args, desc)) +- lines = string.split(self.comment, '\n') +- if lines[0] == '*': +- del lines[0] +- if lines[0] != "* %s:" % (name): +- if not quiet: +- self.warning("Misformatted macro comment for %s" % (name)) +- self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0])) +- return((args, desc)) +- del lines[0] +- while lines[0] == '*': +- del lines[0] +- while len(lines) > 0 and lines[0][0:3] == '* @': +- l = lines[0][3:] +- try: +- (arg, desc) = string.split(l, ':', 1) +- desc=string.strip(desc) +- arg=string.strip(arg) ++ if not quiet: ++ self.warning("Missing * in macro comment for %s" % (name)) ++ return((args, desc)) ++ lines = string.split(self.comment, '\n') ++ if lines[0] == '*': ++ del lines[0] ++ if lines[0] != "* %s:" % (name): ++ if not quiet: ++ self.warning("Misformatted macro comment for %s" % (name)) ++ self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0])) ++ return((args, desc)) ++ del lines[0] ++ while lines[0] == '*': ++ del lines[0] ++ while len(lines) > 0 and lines[0][0:3] == '* @': ++ l = lines[0][3:] ++ try: ++ (arg, desc) = string.split(l, ':', 1) ++ desc=string.strip(desc) ++ arg=string.strip(arg) + except: +- if not quiet: +- self.warning("Misformatted macro comment for %s" % (name)) +- self.warning(" problem with '%s'" % (lines[0])) +- del lines[0] +- continue +- del lines[0] +- l = string.strip(lines[0]) +- while len(l) > 2 and l[0:3] != '* @': +- while l[0] == '*': +- l = l[1:] +- desc = desc + ' ' + string.strip(l) +- del lines[0] +- if len(lines) == 0: +- break +- l = lines[0] ++ if not quiet: ++ self.warning("Misformatted macro comment for %s" % (name)) ++ self.warning(" problem with '%s'" % (lines[0])) ++ del lines[0] ++ continue ++ del lines[0] ++ l = string.strip(lines[0]) ++ while len(l) > 2 and l[0:3] != '* @': ++ while l[0] == '*': ++ l = l[1:] ++ desc = desc + ' ' + string.strip(l) ++ del lines[0] ++ if len(lines) == 0: ++ break ++ l = lines[0] + args.append((arg, desc)) +- while len(lines) > 0 and lines[0] == '*': +- del lines[0] +- desc = "" +- while len(lines) > 0: +- l = lines[0] +- while len(l) > 0 and l[0] == '*': +- l = l[1:] +- l = string.strip(l) +- desc = desc + " " + l +- del lines[0] +- +- desc = string.strip(desc) +- +- if quiet == 0: +- if desc == "": +- self.warning("Macro comment for %s lack description of the macro" % (name)) ++ while len(lines) > 0 and lines[0] == '*': ++ del lines[0] ++ desc = "" ++ while len(lines) > 0: ++ l = lines[0] ++ while len(l) > 0 and l[0] == '*': ++ l = l[1:] ++ l = string.strip(l) ++ desc = desc + " " + l ++ del lines[0] ++ ++ desc = string.strip(desc) ++ ++ if quiet == 0: ++ if desc == "": ++ self.warning("Macro comment for %s lack description of the macro" % (name)) + +- return((args, desc)) ++ return((args, desc)) + + # + # Parse a comment block and merge the informations found in the +@@ -693,167 +693,167 @@ + # + def mergeFunctionComment(self, name, description, quiet = 0): + if name == 'main': +- quiet = 1 ++ quiet = 1 + if name[0:2] == '__': +- quiet = 1 ++ quiet = 1 + +- (ret, args) = description +- desc = "" +- retdesc = "" ++ (ret, args) = description ++ desc = "" ++ retdesc = "" + + if self.comment == None: +- if not quiet: +- self.warning("Missing comment for function %s" % (name)) +- return(((ret[0], retdesc), args, desc)) ++ if not quiet: ++ self.warning("Missing comment for function %s" % (name)) ++ return(((ret[0], retdesc), args, desc)) + if self.comment[0] != '*': +- if not quiet: +- self.warning("Missing * in function comment for %s" % (name)) +- return(((ret[0], retdesc), args, desc)) +- lines = string.split(self.comment, '\n') +- if lines[0] == '*': +- del lines[0] +- if lines[0] != "* %s:" % (name): +- if not quiet: +- self.warning("Misformatted function comment for %s" % (name)) +- self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0])) +- return(((ret[0], retdesc), args, desc)) +- del lines[0] +- while lines[0] == '*': +- del lines[0] +- nbargs = len(args) +- while len(lines) > 0 and lines[0][0:3] == '* @': +- l = lines[0][3:] +- try: +- (arg, desc) = string.split(l, ':', 1) +- desc=string.strip(desc) +- arg=string.strip(arg) ++ if not quiet: ++ self.warning("Missing * in function comment for %s" % (name)) ++ return(((ret[0], retdesc), args, desc)) ++ lines = string.split(self.comment, '\n') ++ if lines[0] == '*': ++ del lines[0] ++ if lines[0] != "* %s:" % (name): ++ if not quiet: ++ self.warning("Misformatted function comment for %s" % (name)) ++ self.warning(" Expecting '* %s:' got '%s'" % (name, lines[0])) ++ return(((ret[0], retdesc), args, desc)) ++ del lines[0] ++ while lines[0] == '*': ++ del lines[0] ++ nbargs = len(args) ++ while len(lines) > 0 and lines[0][0:3] == '* @': ++ l = lines[0][3:] ++ try: ++ (arg, desc) = string.split(l, ':', 1) ++ desc=string.strip(desc) ++ arg=string.strip(arg) + except: +- if not quiet: +- self.warning("Misformatted function comment for %s" % (name)) +- self.warning(" problem with '%s'" % (lines[0])) +- del lines[0] +- continue +- del lines[0] +- l = string.strip(lines[0]) +- while len(l) > 2 and l[0:3] != '* @': +- while l[0] == '*': +- l = l[1:] +- desc = desc + ' ' + string.strip(l) +- del lines[0] +- if len(lines) == 0: +- break +- l = lines[0] +- i = 0 +- while i < nbargs: +- if args[i][1] == arg: +- args[i] = (args[i][0], arg, desc) +- break; +- i = i + 1 +- if i >= nbargs: +- if not quiet: +- self.warning("Unable to find arg %s from function comment for %s" % ( +- arg, name)) +- while len(lines) > 0 and lines[0] == '*': +- del lines[0] +- desc = "" +- while len(lines) > 0: +- l = lines[0] +- while len(l) > 0 and l[0] == '*': +- l = l[1:] +- l = string.strip(l) +- if len(l) >= 6 and l[0:6] == "return" or l[0:6] == "Return": +- try: +- l = string.split(l, ' ', 1)[1] +- except: +- l = "" +- retdesc = string.strip(l) +- del lines[0] +- while len(lines) > 0: +- l = lines[0] +- while len(l) > 0 and l[0] == '*': +- l = l[1:] +- l = string.strip(l) +- retdesc = retdesc + " " + l +- del lines[0] +- else: +- desc = desc + " " + l +- del lines[0] +- +- retdesc = string.strip(retdesc) +- desc = string.strip(desc) +- +- if quiet == 0: +- # +- # report missing comments +- # +- i = 0 +- while i < nbargs: +- if args[i][2] == None and args[i][0] != "void" and args[i][1] != None: +- self.warning("Function comment for %s lack description of arg %s" % (name, args[i][1])) +- i = i + 1 +- if retdesc == "" and ret[0] != "void": +- self.warning("Function comment for %s lack description of return value" % (name)) +- if desc == "": +- self.warning("Function comment for %s lack description of the function" % (name)) ++ if not quiet: ++ self.warning("Misformatted function comment for %s" % (name)) ++ self.warning(" problem with '%s'" % (lines[0])) ++ del lines[0] ++ continue ++ del lines[0] ++ l = string.strip(lines[0]) ++ while len(l) > 2 and l[0:3] != '* @': ++ while l[0] == '*': ++ l = l[1:] ++ desc = desc + ' ' + string.strip(l) ++ del lines[0] ++ if len(lines) == 0: ++ break ++ l = lines[0] ++ i = 0 ++ while i < nbargs: ++ if args[i][1] == arg: ++ args[i] = (args[i][0], arg, desc) ++ break; ++ i = i + 1 ++ if i >= nbargs: ++ if not quiet: ++ self.warning("Unable to find arg %s from function comment for %s" % ( ++ arg, name)) ++ while len(lines) > 0 and lines[0] == '*': ++ del lines[0] ++ desc = "" ++ while len(lines) > 0: ++ l = lines[0] ++ while len(l) > 0 and l[0] == '*': ++ l = l[1:] ++ l = string.strip(l) ++ if len(l) >= 6 and l[0:6] == "return" or l[0:6] == "Return": ++ try: ++ l = string.split(l, ' ', 1)[1] ++ except: ++ l = "" ++ retdesc = string.strip(l) ++ del lines[0] ++ while len(lines) > 0: ++ l = lines[0] ++ while len(l) > 0 and l[0] == '*': ++ l = l[1:] ++ l = string.strip(l) ++ retdesc = retdesc + " " + l ++ del lines[0] ++ else: ++ desc = desc + " " + l ++ del lines[0] ++ ++ retdesc = string.strip(retdesc) ++ desc = string.strip(desc) ++ ++ if quiet == 0: ++ # ++ # report missing comments ++ # ++ i = 0 ++ while i < nbargs: ++ if args[i][2] == None and args[i][0] != "void" and args[i][1] != None: ++ self.warning("Function comment for %s lack description of arg %s" % (name, args[i][1])) ++ i = i + 1 ++ if retdesc == "" and ret[0] != "void": ++ self.warning("Function comment for %s lack description of return value" % (name)) ++ if desc == "": ++ self.warning("Function comment for %s lack description of the function" % (name)) + + +- return(((ret[0], retdesc), args, desc)) ++ return(((ret[0], retdesc), args, desc)) + + def parsePreproc(self, token): +- if debug: +- print "=> preproc ", token, self.lexer.tokens ++ if debug: ++ print("=> preproc ", token, self.lexer.tokens) + name = token[1] +- if name == "#include": +- token = self.lexer.token() +- if token == None: +- return None +- if token[0] == 'preproc': +- self.index_add(token[1], self.filename, not self.is_header, +- "include") +- return self.lexer.token() +- return token +- if name == "#define": +- token = self.lexer.token() +- if token == None: +- return None +- if token[0] == 'preproc': +- # TODO macros with arguments +- name = token[1] +- lst = [] +- token = self.lexer.token() +- while token != None and token[0] == 'preproc' and \ +- token[1][0] != '#': +- lst.append(token[1]) +- token = self.lexer.token() ++ if name == "#include": ++ token = self.lexer.token() ++ if token == None: ++ return None ++ if token[0] == 'preproc': ++ self.index_add(token[1], self.filename, not self.is_header, ++ "include") ++ return self.lexer.token() ++ return token ++ if name == "#define": ++ token = self.lexer.token() ++ if token == None: ++ return None ++ if token[0] == 'preproc': ++ # TODO macros with arguments ++ name = token[1] ++ lst = [] ++ token = self.lexer.token() ++ while token != None and token[0] == 'preproc' and \ ++ token[1][0] != '#': ++ lst.append(token[1]) ++ token = self.lexer.token() + try: +- name = string.split(name, '(') [0] ++ name = string.split(name, '(') [0] + except: + pass + info = self.parseMacroComment(name, not self.is_header) +- self.index_add(name, self.filename, not self.is_header, +- "macro", info) +- return token +- if (name == "#ifdef" or name == "#ifndef") and self.is_header: +- try: +- self.defines.append(self.lexer.tokens[0][1]) +- if string.find(self.lexer.tokens[0][1], 'ENABLED') != -1: +- self.conditionals.append(self.lexer.tokens[0][1]) +-# print self.conditionals +-# print self.defines +- except: +- pass +- if name == "#endif" and self.is_header: +- if self.conditionals != [] and self.defines != [] and \ +- self.defines[-1] == self.conditionals[-1]: +- self.conditionals = self.conditionals[:-1] +- self.defines = self.defines[:-1] +-# print self.defines +-# print self.conditionals +- token = self.lexer.token() +- while token != None and token[0] == 'preproc' and \ +- token[1][0] != '#': +- token = self.lexer.token() +- return token ++ self.index_add(name, self.filename, not self.is_header, ++ "macro", info) ++ return token ++ if (name == "#ifdef" or name == "#ifndef") and self.is_header: ++ try: ++ self.defines.append(self.lexer.tokens[0][1]) ++ if string.find(self.lexer.tokens[0][1], 'ENABLED') != -1: ++ self.conditionals.append(self.lexer.tokens[0][1]) ++# print(self.conditionals) ++# print(self.defines) ++ except: ++ pass ++ if name == "#endif" and self.is_header: ++ if self.conditionals != [] and self.defines != [] and \ ++ self.defines[-1] == self.conditionals[-1]: ++ self.conditionals = self.conditionals[:-1] ++ self.defines = self.defines[:-1] ++# print(self.defines) ++# print(self.conditionals) ++ token = self.lexer.token() ++ while token != None and token[0] == 'preproc' and \ ++ token[1][0] != '#': ++ token = self.lexer.token() ++ return token + + # + # token acquisition on top of the lexer, it handle internally +@@ -864,218 +864,218 @@ + global ignored_words + + token = self.lexer.token() +- while token != None: +- if token[0] == 'comment': +- token = self.parseComment(token) +- continue +- elif token[0] == 'preproc': +- token = self.parsePreproc(token) +- continue +- elif token[0] == "name" and ignored_words.has_key(token[1]): +- (n, info) = ignored_words[token[1]] +- i = 0 +- while i < n: +- token = self.lexer.token() +- i = i + 1 +- token = self.lexer.token() +- continue +- else: +- if debug: +- print "=> ", token +- return token +- return None ++ while token != None: ++ if token[0] == 'comment': ++ token = self.parseComment(token) ++ continue ++ elif token[0] == 'preproc': ++ token = self.parsePreproc(token) ++ continue ++ elif token[0] == "name" and ignored_words.has_key(token[1]): ++ (n, info) = ignored_words[token[1]] ++ i = 0 ++ while i < n: ++ token = self.lexer.token() ++ i = i + 1 ++ token = self.lexer.token() ++ continue ++ else: ++ if debug: ++ print("=> ", token) ++ return token ++ return None + + # + # Parse a typedef, it records the type and its name. + # + def parseTypedef(self, token): + if token == None: +- return None +- token = self.parseType(token) +- if token == None: +- self.error("parsing typedef") +- return None +- base_type = self.type +- type = base_type +- #self.debug("end typedef type", token) +- while token != None: +- if token[0] == "name": +- name = token[1] +- signature = self.signature +- if signature != None: +- type = string.split(type, '(')[0] +- d = self.mergeFunctionComment(name, +- ((type, None), signature), 1) +- self.index_add(name, self.filename, not self.is_header, +- "functype", d) +- else: +- if base_type == "struct": +- self.index_add(name, self.filename, not self.is_header, +- "struct", type) +- base_type = "struct " + name +- else: +- self.index_add(name, self.filename, not self.is_header, +- "typedef", type) +- token = self.token() +- else: +- self.error("parsing typedef: expecting a name") +- return token +- #self.debug("end typedef", token) +- if token != None and token[0] == 'sep' and token[1] == ',': +- type = base_type +- token = self.token() +- while token != None and token[0] == "op": +- type = type + token[1] +- token = self.token() +- elif token != None and token[0] == 'sep' and token[1] == ';': +- break; +- elif token != None and token[0] == 'name': +- type = base_type +- continue; +- else: +- self.error("parsing typedef: expecting ';'", token) +- return token +- token = self.token() +- return token +- ++ return None ++ token = self.parseType(token) ++ if token == None: ++ self.error("parsing typedef") ++ return None ++ base_type = self.type ++ type = base_type ++ #self.debug("end typedef type", token) ++ while token != None: ++ if token[0] == "name": ++ name = token[1] ++ signature = self.signature ++ if signature != None: ++ type = string.split(type, '(')[0] ++ d = self.mergeFunctionComment(name, ++ ((type, None), signature), 1) ++ self.index_add(name, self.filename, not self.is_header, ++ "functype", d) ++ else: ++ if base_type == "struct": ++ self.index_add(name, self.filename, not self.is_header, ++ "struct", type) ++ base_type = "struct " + name ++ else: ++ self.index_add(name, self.filename, not self.is_header, ++ "typedef", type) ++ token = self.token() ++ else: ++ self.error("parsing typedef: expecting a name") ++ return token ++ #self.debug("end typedef", token) ++ if token != None and token[0] == 'sep' and token[1] == ',': ++ type = base_type ++ token = self.token() ++ while token != None and token[0] == "op": ++ type = type + token[1] ++ token = self.token() ++ elif token != None and token[0] == 'sep' and token[1] == ';': ++ break; ++ elif token != None and token[0] == 'name': ++ type = base_type ++ continue; ++ else: ++ self.error("parsing typedef: expecting ';'", token) ++ return token ++ token = self.token() ++ return token ++ + # + # Parse a C code block, used for functions it parse till + # the balancing } included + # + def parseBlock(self, token): + while token != None: +- if token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseBlock(token) +- elif token[0] == "sep" and token[1] == "}": +- self.comment = None +- token = self.token() +- return token +- else: +- if self.collect_ref == 1: +- oldtok = token +- token = self.token() +- if oldtok[0] == "name" and oldtok[1][0:3] == "xml": +- if token[0] == "sep" and token[1] == "(": +- self.index_add_ref(oldtok[1], self.filename, +- 0, "function") +- token = self.token() +- elif token[0] == "name": +- token = self.token() +- if token[0] == "sep" and (token[1] == ";" or +- token[1] == "," or token[1] == "="): +- self.index_add_ref(oldtok[1], self.filename, +- 0, "type") +- elif oldtok[0] == "name" and oldtok[1][0:4] == "XML_": +- self.index_add_ref(oldtok[1], self.filename, +- 0, "typedef") +- elif oldtok[0] == "name" and oldtok[1][0:7] == "LIBXML_": +- self.index_add_ref(oldtok[1], self.filename, +- 0, "typedef") +- +- else: +- token = self.token() +- return token ++ if token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseBlock(token) ++ elif token[0] == "sep" and token[1] == "}": ++ self.comment = None ++ token = self.token() ++ return token ++ else: ++ if self.collect_ref == 1: ++ oldtok = token ++ token = self.token() ++ if oldtok[0] == "name" and oldtok[1][0:3] == "xml": ++ if token[0] == "sep" and token[1] == "(": ++ self.index_add_ref(oldtok[1], self.filename, ++ 0, "function") ++ token = self.token() ++ elif token[0] == "name": ++ token = self.token() ++ if token[0] == "sep" and (token[1] == ";" or ++ token[1] == "," or token[1] == "="): ++ self.index_add_ref(oldtok[1], self.filename, ++ 0, "type") ++ elif oldtok[0] == "name" and oldtok[1][0:4] == "XML_": ++ self.index_add_ref(oldtok[1], self.filename, ++ 0, "typedef") ++ elif oldtok[0] == "name" and oldtok[1][0:7] == "LIBXML_": ++ self.index_add_ref(oldtok[1], self.filename, ++ 0, "typedef") ++ ++ else: ++ token = self.token() ++ return token + + # + # Parse a C struct definition till the balancing } + # + def parseStruct(self, token): + fields = [] +- #self.debug("start parseStruct", token) ++ #self.debug("start parseStruct", token) + while token != None: +- if token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseTypeBlock(token) +- elif token[0] == "sep" and token[1] == "}": +- self.struct_fields = fields +- #self.debug("end parseStruct", token) +- #print fields +- token = self.token() +- return token +- else: +- base_type = self.type +- #self.debug("before parseType", token) +- token = self.parseType(token) +- #self.debug("after parseType", token) +- if token != None and token[0] == "name": +- fname = token[1] +- token = self.token() +- if token[0] == "sep" and token[1] == ";": +- self.comment = None +- token = self.token() +- fields.append((self.type, fname, self.comment)) +- self.comment = None +- else: +- self.error("parseStruct: expecting ;", token) +- elif token != None and token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseTypeBlock(token) +- if token != None and token[0] == "name": +- token = self.token() +- if token != None and token[0] == "sep" and token[1] == ";": +- token = self.token() +- else: +- self.error("parseStruct: expecting ;", token) +- else: +- self.error("parseStruct: name", token) +- token = self.token() +- self.type = base_type; ++ if token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseTypeBlock(token) ++ elif token[0] == "sep" and token[1] == "}": ++ self.struct_fields = fields ++ #self.debug("end parseStruct", token) ++ #print(fields) ++ token = self.token() ++ return token ++ else: ++ base_type = self.type ++ #self.debug("before parseType", token) ++ token = self.parseType(token) ++ #self.debug("after parseType", token) ++ if token != None and token[0] == "name": ++ fname = token[1] ++ token = self.token() ++ if token[0] == "sep" and token[1] == ";": ++ self.comment = None ++ token = self.token() ++ fields.append((self.type, fname, self.comment)) ++ self.comment = None ++ else: ++ self.error("parseStruct: expecting ;", token) ++ elif token != None and token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseTypeBlock(token) ++ if token != None and token[0] == "name": ++ token = self.token() ++ if token != None and token[0] == "sep" and token[1] == ";": ++ token = self.token() ++ else: ++ self.error("parseStruct: expecting ;", token) ++ else: ++ self.error("parseStruct: name", token) ++ token = self.token() ++ self.type = base_type; + self.struct_fields = fields +- #self.debug("end parseStruct", token) +- #print fields +- return token ++ #self.debug("end parseStruct", token) ++ #print(fields) ++ return token + + # + # Parse a C enum block, parse till the balancing } + # + def parseEnumBlock(self, token): + self.enums = [] +- name = None +- self.comment = None +- comment = "" +- value = "0" ++ name = None ++ self.comment = None ++ comment = "" ++ value = "0" + while token != None: +- if token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseTypeBlock(token) +- elif token[0] == "sep" and token[1] == "}": +- if name != None: +- if self.comment != None: +- comment = self.comment +- self.comment = None +- self.enums.append((name, value, comment)) +- token = self.token() +- return token +- elif token[0] == "name": +- if name != None: +- if self.comment != None: +- comment = string.strip(self.comment) +- self.comment = None +- self.enums.append((name, value, comment)) +- name = token[1] +- comment = "" +- token = self.token() +- if token[0] == "op" and token[1][0] == "=": +- value = "" +- if len(token[1]) > 1: +- value = token[1][1:] +- token = self.token() +- while token[0] != "sep" or (token[1] != ',' and +- token[1] != '}'): +- value = value + token[1] +- token = self.token() +- else: +- try: +- value = "%d" % (int(value) + 1) +- except: +- self.warning("Failed to compute value of enum %s" % (name)) +- value="" +- if token[0] == "sep" and token[1] == ",": +- token = self.token() +- else: +- token = self.token() +- return token ++ if token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseTypeBlock(token) ++ elif token[0] == "sep" and token[1] == "}": ++ if name != None: ++ if self.comment != None: ++ comment = self.comment ++ self.comment = None ++ self.enums.append((name, value, comment)) ++ token = self.token() ++ return token ++ elif token[0] == "name": ++ if name != None: ++ if self.comment != None: ++ comment = string.strip(self.comment) ++ self.comment = None ++ self.enums.append((name, value, comment)) ++ name = token[1] ++ comment = "" ++ token = self.token() ++ if token[0] == "op" and token[1][0] == "=": ++ value = "" ++ if len(token[1]) > 1: ++ value = token[1][1:] ++ token = self.token() ++ while token[0] != "sep" or (token[1] != ',' and ++ token[1] != '}'): ++ value = value + token[1] ++ token = self.token() ++ else: ++ try: ++ value = "%d" % (int(value) + 1) ++ except: ++ self.warning("Failed to compute value of enum %s" % (name)) ++ value="" ++ if token[0] == "sep" and token[1] == ",": ++ token = self.token() ++ else: ++ token = self.token() ++ return token + + # + # Parse a C definition block, used for structs it parse till +@@ -1083,15 +1083,15 @@ + # + def parseTypeBlock(self, token): + while token != None: +- if token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseTypeBlock(token) +- elif token[0] == "sep" and token[1] == "}": +- token = self.token() +- return token +- else: +- token = self.token() +- return token ++ if token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseTypeBlock(token) ++ elif token[0] == "sep" and token[1] == "}": ++ token = self.token() ++ return token ++ else: ++ token = self.token() ++ return token + + # + # Parse a type: the fact that the type name can either occur after +@@ -1100,198 +1100,198 @@ + # + def parseType(self, token): + self.type = "" +- self.struct_fields = [] ++ self.struct_fields = [] + self.signature = None +- if token == None: +- return token ++ if token == None: ++ return token + +- while token[0] == "name" and ( +- token[1] == "const" or token[1] == "unsigned"): +- if self.type == "": +- self.type = token[1] +- else: +- self.type = self.type + " " + token[1] +- token = self.token() ++ while token[0] == "name" and ( ++ token[1] == "const" or token[1] == "unsigned"): ++ if self.type == "": ++ self.type = token[1] ++ else: ++ self.type = self.type + " " + token[1] ++ token = self.token() + + if token[0] == "name" and (token[1] == "long" or token[1] == "short"): +- if self.type == "": +- self.type = token[1] +- else: +- self.type = self.type + " " + token[1] +- if token[0] == "name" and token[1] == "int": +- if self.type == "": +- self.type = tmp[1] +- else: +- self.type = self.type + " " + tmp[1] +- ++ if self.type == "": ++ self.type = token[1] ++ else: ++ self.type = self.type + " " + token[1] ++ if token[0] == "name" and token[1] == "int": ++ if self.type == "": ++ self.type = tmp[1] ++ else: ++ self.type = self.type + " " + tmp[1] ++ + elif token[0] == "name" and token[1] == "struct": +- if self.type == "": +- self.type = token[1] +- else: +- self.type = self.type + " " + token[1] +- token = self.token() +- nametok = None +- if token[0] == "name": +- nametok = token +- token = self.token() +- if token != None and token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseStruct(token) +- elif token != None and token[0] == "op" and token[1] == "*": +- self.type = self.type + " " + nametok[1] + " *" +- token = self.token() +- while token != None and token[0] == "op" and token[1] == "*": +- self.type = self.type + " *" +- token = self.token() +- if token[0] == "name": +- nametok = token +- token = self.token() +- else: +- self.error("struct : expecting name", token) +- return token +- elif token != None and token[0] == "name" and nametok != None: +- self.type = self.type + " " + nametok[1] +- return token +- +- if nametok != None: +- self.lexer.push(token) +- token = nametok +- return token ++ if self.type == "": ++ self.type = token[1] ++ else: ++ self.type = self.type + " " + token[1] ++ token = self.token() ++ nametok = None ++ if token[0] == "name": ++ nametok = token ++ token = self.token() ++ if token != None and token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseStruct(token) ++ elif token != None and token[0] == "op" and token[1] == "*": ++ self.type = self.type + " " + nametok[1] + " *" ++ token = self.token() ++ while token != None and token[0] == "op" and token[1] == "*": ++ self.type = self.type + " *" ++ token = self.token() ++ if token[0] == "name": ++ nametok = token ++ token = self.token() ++ else: ++ self.error("struct : expecting name", token) ++ return token ++ elif token != None and token[0] == "name" and nametok != None: ++ self.type = self.type + " " + nametok[1] ++ return token ++ ++ if nametok != None: ++ self.lexer.push(token) ++ token = nametok ++ return token + + elif token[0] == "name" and token[1] == "enum": +- if self.type == "": +- self.type = token[1] +- else: +- self.type = self.type + " " + token[1] +- self.enums = [] +- token = self.token() +- if token != None and token[0] == "sep" and token[1] == "{": +- token = self.token() +- token = self.parseEnumBlock(token) +- else: +- self.error("parsing enum: expecting '{'", token) +- enum_type = None +- if token != None and token[0] != "name": +- self.lexer.push(token) +- token = ("name", "enum") +- else: +- enum_type = token[1] +- for enum in self.enums: +- self.index_add(enum[0], self.filename, +- not self.is_header, "enum", +- (enum[1], enum[2], enum_type)) +- return token +- +- elif token[0] == "name": +- if self.type == "": +- self.type = token[1] +- else: +- self.type = self.type + " " + token[1] +- else: +- self.error("parsing type %s: expecting a name" % (self.type), +- token) +- return token +- token = self.token() ++ if self.type == "": ++ self.type = token[1] ++ else: ++ self.type = self.type + " " + token[1] ++ self.enums = [] ++ token = self.token() ++ if token != None and token[0] == "sep" and token[1] == "{": ++ token = self.token() ++ token = self.parseEnumBlock(token) ++ else: ++ self.error("parsing enum: expecting '{'", token) ++ enum_type = None ++ if token != None and token[0] != "name": ++ self.lexer.push(token) ++ token = ("name", "enum") ++ else: ++ enum_type = token[1] ++ for enum in self.enums: ++ self.index_add(enum[0], self.filename, ++ not self.is_header, "enum", ++ (enum[1], enum[2], enum_type)) ++ return token ++ ++ elif token[0] == "name": ++ if self.type == "": ++ self.type = token[1] ++ else: ++ self.type = self.type + " " + token[1] ++ else: ++ self.error("parsing type %s: expecting a name" % (self.type), ++ token) ++ return token ++ token = self.token() + while token != None and (token[0] == "op" or +- token[0] == "name" and token[1] == "const"): +- self.type = self.type + " " + token[1] +- token = self.token() +- +- # +- # if there is a parenthesis here, this means a function type +- # +- if token != None and token[0] == "sep" and token[1] == '(': +- self.type = self.type + token[1] +- token = self.token() +- while token != None and token[0] == "op" and token[1] == '*': +- self.type = self.type + token[1] +- token = self.token() +- if token == None or token[0] != "name" : +- self.error("parsing function type, name expected", token); +- return token +- self.type = self.type + token[1] +- nametok = token +- token = self.token() +- if token != None and token[0] == "sep" and token[1] == ')': +- self.type = self.type + token[1] +- token = self.token() +- if token != None and token[0] == "sep" and token[1] == '(': +- token = self.token() +- type = self.type; +- token = self.parseSignature(token); +- self.type = type; +- else: +- self.error("parsing function type, '(' expected", token); +- return token +- else: +- self.error("parsing function type, ')' expected", token); +- return token +- self.lexer.push(token) +- token = nametok +- return token ++ token[0] == "name" and token[1] == "const"): ++ self.type = self.type + " " + token[1] ++ token = self.token() + + # +- # do some lookahead for arrays +- # +- if token != None and token[0] == "name": +- nametok = token +- token = self.token() +- if token != None and token[0] == "sep" and token[1] == '[': +- self.type = self.type + nametok[1] +- while token != None and token[0] == "sep" and token[1] == '[': +- self.type = self.type + token[1] +- token = self.token() +- while token != None and token[0] != 'sep' and \ +- token[1] != ']' and token[1] != ';': +- self.type = self.type + token[1] +- token = self.token() +- if token != None and token[0] == 'sep' and token[1] == ']': +- self.type = self.type + token[1] +- token = self.token() +- else: +- self.error("parsing array type, ']' expected", token); +- return token +- elif token != None and token[0] == "sep" and token[1] == ':': +- # remove :12 in case it's a limited int size +- token = self.token() +- token = self.token() +- self.lexer.push(token) +- token = nametok ++ # if there is a parenthesis here, this means a function type ++ # ++ if token != None and token[0] == "sep" and token[1] == '(': ++ self.type = self.type + token[1] ++ token = self.token() ++ while token != None and token[0] == "op" and token[1] == '*': ++ self.type = self.type + token[1] ++ token = self.token() ++ if token == None or token[0] != "name" : ++ self.error("parsing function type, name expected", token); ++ return token ++ self.type = self.type + token[1] ++ nametok = token ++ token = self.token() ++ if token != None and token[0] == "sep" and token[1] == ')': ++ self.type = self.type + token[1] ++ token = self.token() ++ if token != None and token[0] == "sep" and token[1] == '(': ++ token = self.token() ++ type = self.type; ++ token = self.parseSignature(token); ++ self.type = type; ++ else: ++ self.error("parsing function type, '(' expected", token); ++ return token ++ else: ++ self.error("parsing function type, ')' expected", token); ++ return token ++ self.lexer.push(token) ++ token = nametok ++ return token + +- return token ++ # ++ # do some lookahead for arrays ++ # ++ if token != None and token[0] == "name": ++ nametok = token ++ token = self.token() ++ if token != None and token[0] == "sep" and token[1] == '[': ++ self.type = self.type + nametok[1] ++ while token != None and token[0] == "sep" and token[1] == '[': ++ self.type = self.type + token[1] ++ token = self.token() ++ while token != None and token[0] != 'sep' and \ ++ token[1] != ']' and token[1] != ';': ++ self.type = self.type + token[1] ++ token = self.token() ++ if token != None and token[0] == 'sep' and token[1] == ']': ++ self.type = self.type + token[1] ++ token = self.token() ++ else: ++ self.error("parsing array type, ']' expected", token); ++ return token ++ elif token != None and token[0] == "sep" and token[1] == ':': ++ # remove :12 in case it's a limited int size ++ token = self.token() ++ token = self.token() ++ self.lexer.push(token) ++ token = nametok ++ ++ return token + + # + # Parse a signature: '(' has been parsed and we scan the type definition + # up to the ')' included + def parseSignature(self, token): + signature = [] +- if token != None and token[0] == "sep" and token[1] == ')': +- self.signature = [] +- token = self.token() +- return token +- while token != None: +- token = self.parseType(token) +- if token != None and token[0] == "name": +- signature.append((self.type, token[1], None)) +- token = self.token() +- elif token != None and token[0] == "sep" and token[1] == ',': +- token = self.token() +- continue +- elif token != None and token[0] == "sep" and token[1] == ')': +- # only the type was provided +- if self.type == "...": +- signature.append((self.type, "...", None)) +- else: +- signature.append((self.type, None, None)) +- if token != None and token[0] == "sep": +- if token[1] == ',': +- token = self.token() +- continue +- elif token[1] == ')': +- token = self.token() +- break +- self.signature = signature +- return token ++ if token != None and token[0] == "sep" and token[1] == ')': ++ self.signature = [] ++ token = self.token() ++ return token ++ while token != None: ++ token = self.parseType(token) ++ if token != None and token[0] == "name": ++ signature.append((self.type, token[1], None)) ++ token = self.token() ++ elif token != None and token[0] == "sep" and token[1] == ',': ++ token = self.token() ++ continue ++ elif token != None and token[0] == "sep" and token[1] == ')': ++ # only the type was provided ++ if self.type == "...": ++ signature.append((self.type, "...", None)) ++ else: ++ signature.append((self.type, None, None)) ++ if token != None and token[0] == "sep": ++ if token[1] == ',': ++ token = self.token() ++ continue ++ elif token[1] == ')': ++ token = self.token() ++ break ++ self.signature = signature ++ return token + + # + # Parse a global definition, be it a type, variable or function +@@ -1300,573 +1300,573 @@ + def parseGlobal(self, token): + static = 0 + if token[1] == 'extern': +- token = self.token() +- if token == None: +- return token +- if token[0] == 'string': +- if token[1] == 'C': +- token = self.token() +- if token == None: +- return token +- if token[0] == 'sep' and token[1] == "{": +- token = self.token() +-# print 'Entering extern "C line ', self.lineno() +- while token != None and (token[0] != 'sep' or +- token[1] != "}"): +- if token[0] == 'name': +- token = self.parseGlobal(token) +- else: +- self.error( +- "token %s %s unexpected at the top level" % ( +- token[0], token[1])) +- token = self.parseGlobal(token) +-# print 'Exiting extern "C" line', self.lineno() +- token = self.token() +- return token +- else: +- return token +- elif token[1] == 'static': +- static = 1 +- token = self.token() +- if token == None or token[0] != 'name': +- return token +- +- if token[1] == 'typedef': +- token = self.token() +- return self.parseTypedef(token) +- else: +- token = self.parseType(token) +- type_orig = self.type +- if token == None or token[0] != "name": +- return token +- type = type_orig +- self.name = token[1] +- token = self.token() +- while token != None and (token[0] == "sep" or token[0] == "op"): +- if token[0] == "sep": +- if token[1] == "[": +- type = type + token[1] +- token = self.token() +- while token != None and (token[0] != "sep" or \ +- token[1] != ";"): +- type = type + token[1] +- token = self.token() +- +- if token != None and token[0] == "op" and token[1] == "=": +- # +- # Skip the initialization of the variable +- # +- token = self.token() +- if token[0] == 'sep' and token[1] == '{': +- token = self.token() +- token = self.parseBlock(token) +- else: +- self.comment = None +- while token != None and (token[0] != "sep" or \ +- (token[1] != ';' and token[1] != ',')): +- token = self.token() +- self.comment = None +- if token == None or token[0] != "sep" or (token[1] != ';' and +- token[1] != ','): +- self.error("missing ';' or ',' after value") +- +- if token != None and token[0] == "sep": +- if token[1] == ";": +- self.comment = None +- token = self.token() +- if type == "struct": +- self.index_add(self.name, self.filename, +- not self.is_header, "struct", self.struct_fields) +- else: +- self.index_add(self.name, self.filename, +- not self.is_header, "variable", type) +- break +- elif token[1] == "(": +- token = self.token() +- token = self.parseSignature(token) +- if token == None: +- return None +- if token[0] == "sep" and token[1] == ";": +- d = self.mergeFunctionComment(self.name, +- ((type, None), self.signature), 1) +- self.index_add(self.name, self.filename, static, +- "function", d) +- token = self.token() +- elif token[0] == "sep" and token[1] == "{": +- d = self.mergeFunctionComment(self.name, +- ((type, None), self.signature), static) +- self.index_add(self.name, self.filename, static, +- "function", d) +- token = self.token() +- token = self.parseBlock(token); +- elif token[1] == ',': +- self.comment = None +- self.index_add(self.name, self.filename, static, +- "variable", type) +- type = type_orig +- token = self.token() +- while token != None and token[0] == "sep": +- type = type + token[1] +- token = self.token() +- if token != None and token[0] == "name": +- self.name = token[1] +- token = self.token() +- else: +- break +- +- return token ++ token = self.token() ++ if token == None: ++ return token ++ if token[0] == 'string': ++ if token[1] == 'C': ++ token = self.token() ++ if token == None: ++ return token ++ if token[0] == 'sep' and token[1] == "{": ++ token = self.token() ++# print('Entering extern "C line ', self.lineno()) ++ while token != None and (token[0] != 'sep' or ++ token[1] != "}"): ++ if token[0] == 'name': ++ token = self.parseGlobal(token) ++ else: ++ self.error( ++ "token %s %s unexpected at the top level" % ( ++ token[0], token[1])) ++ token = self.parseGlobal(token) ++# print('Exiting extern "C" line', self.lineno()) ++ token = self.token() ++ return token ++ else: ++ return token ++ elif token[1] == 'static': ++ static = 1 ++ token = self.token() ++ if token == None or token[0] != 'name': ++ return token ++ ++ if token[1] == 'typedef': ++ token = self.token() ++ return self.parseTypedef(token) ++ else: ++ token = self.parseType(token) ++ type_orig = self.type ++ if token == None or token[0] != "name": ++ return token ++ type = type_orig ++ self.name = token[1] ++ token = self.token() ++ while token != None and (token[0] == "sep" or token[0] == "op"): ++ if token[0] == "sep": ++ if token[1] == "[": ++ type = type + token[1] ++ token = self.token() ++ while token != None and (token[0] != "sep" or \ ++ token[1] != ";"): ++ type = type + token[1] ++ token = self.token() ++ ++ if token != None and token[0] == "op" and token[1] == "=": ++ # ++ # Skip the initialization of the variable ++ # ++ token = self.token() ++ if token[0] == 'sep' and token[1] == '{': ++ token = self.token() ++ token = self.parseBlock(token) ++ else: ++ self.comment = None ++ while token != None and (token[0] != "sep" or \ ++ (token[1] != ';' and token[1] != ',')): ++ token = self.token() ++ self.comment = None ++ if token == None or token[0] != "sep" or (token[1] != ';' and ++ token[1] != ','): ++ self.error("missing ';' or ',' after value") ++ ++ if token != None and token[0] == "sep": ++ if token[1] == ";": ++ self.comment = None ++ token = self.token() ++ if type == "struct": ++ self.index_add(self.name, self.filename, ++ not self.is_header, "struct", self.struct_fields) ++ else: ++ self.index_add(self.name, self.filename, ++ not self.is_header, "variable", type) ++ break ++ elif token[1] == "(": ++ token = self.token() ++ token = self.parseSignature(token) ++ if token == None: ++ return None ++ if token[0] == "sep" and token[1] == ";": ++ d = self.mergeFunctionComment(self.name, ++ ((type, None), self.signature), 1) ++ self.index_add(self.name, self.filename, static, ++ "function", d) ++ token = self.token() ++ elif token[0] == "sep" and token[1] == "{": ++ d = self.mergeFunctionComment(self.name, ++ ((type, None), self.signature), static) ++ self.index_add(self.name, self.filename, static, ++ "function", d) ++ token = self.token() ++ token = self.parseBlock(token); ++ elif token[1] == ',': ++ self.comment = None ++ self.index_add(self.name, self.filename, static, ++ "variable", type) ++ type = type_orig ++ token = self.token() ++ while token != None and token[0] == "sep": ++ type = type + token[1] ++ token = self.token() ++ if token != None and token[0] == "name": ++ self.name = token[1] ++ token = self.token() ++ else: ++ break ++ ++ return token + + def parse(self): + self.warning("Parsing %s" % (self.filename)) + token = self.token() +- while token != None: ++ while token != None: + if token[0] == 'name': +- token = self.parseGlobal(token) ++ token = self.parseGlobal(token) + else: +- self.error("token %s %s unexpected at the top level" % ( +- token[0], token[1])) +- token = self.parseGlobal(token) +- return +- self.parseTopComment(self.top_comment) ++ self.error("token %s %s unexpected at the top level" % ( ++ token[0], token[1])) ++ token = self.parseGlobal(token) ++ return ++ self.parseTopComment(self.top_comment) + return self.index +- ++ + + class docBuilder: + """A documentation builder""" + def __init__(self, name, directories=['.'], excludes=[]): + self.name = name + self.directories = directories +- self.excludes = excludes + ignored_files.keys() +- self.modules = {} +- self.headers = {} +- self.idx = index() ++ self.excludes = excludes + ignored_files.keys() ++ self.modules = {} ++ self.headers = {} ++ self.idx = index() + self.xref = {} +- self.index = {} +- if name == 'libxml2': +- self.basename = 'libxml' +- else: +- self.basename = name ++ self.index = {} ++ if name == 'libxml2': ++ self.basename = 'libxml' ++ else: ++ self.basename = name + + def indexString(self, id, str): +- if str == None: +- return +- str = string.replace(str, "'", ' ') +- str = string.replace(str, '"', ' ') +- str = string.replace(str, "/", ' ') +- str = string.replace(str, '*', ' ') +- str = string.replace(str, "[", ' ') +- str = string.replace(str, "]", ' ') +- str = string.replace(str, "(", ' ') +- str = string.replace(str, ")", ' ') +- str = string.replace(str, "<", ' ') +- str = string.replace(str, '>', ' ') +- str = string.replace(str, "&", ' ') +- str = string.replace(str, '#', ' ') +- str = string.replace(str, ",", ' ') +- str = string.replace(str, '.', ' ') +- str = string.replace(str, ';', ' ') +- tokens = string.split(str) +- for token in tokens: +- try: +- c = token[0] +- if string.find(string.letters, c) < 0: +- pass +- elif len(token) < 3: +- pass +- else: +- lower = string.lower(token) +- # TODO: generalize this a bit +- if lower == 'and' or lower == 'the': +- pass +- elif self.xref.has_key(token): +- self.xref[token].append(id) +- else: +- self.xref[token] = [id] +- except: +- pass ++ if str == None: ++ return ++ str = string.replace(str, "'", ' ') ++ str = string.replace(str, '"', ' ') ++ str = string.replace(str, "/", ' ') ++ str = string.replace(str, '*', ' ') ++ str = string.replace(str, "[", ' ') ++ str = string.replace(str, "]", ' ') ++ str = string.replace(str, "(", ' ') ++ str = string.replace(str, ")", ' ') ++ str = string.replace(str, "<", ' ') ++ str = string.replace(str, '>', ' ') ++ str = string.replace(str, "&", ' ') ++ str = string.replace(str, '#', ' ') ++ str = string.replace(str, ",", ' ') ++ str = string.replace(str, '.', ' ') ++ str = string.replace(str, ';', ' ') ++ tokens = string.split(str) ++ for token in tokens: ++ try: ++ c = token[0] ++ if string.find(string.letters, c) < 0: ++ pass ++ elif len(token) < 3: ++ pass ++ else: ++ lower = string.lower(token) ++ # TODO: generalize this a bit ++ if lower == 'and' or lower == 'the': ++ pass ++ elif self.xref.has_key(token): ++ self.xref[token].append(id) ++ else: ++ self.xref[token] = [id] ++ except: ++ pass + + def analyze(self): +- print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys())) +- self.idx.analyze() ++ print("Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys()))) ++ self.idx.analyze() + + def scanHeaders(self): +- for header in self.headers.keys(): +- parser = CParser(header) +- idx = parser.parse() +- self.headers[header] = idx; +- self.idx.merge(idx) ++ for header in self.headers.keys(): ++ parser = CParser(header) ++ idx = parser.parse() ++ self.headers[header] = idx; ++ self.idx.merge(idx) + + def scanModules(self): +- for module in self.modules.keys(): +- parser = CParser(module) +- idx = parser.parse() +- # idx.analyze() +- self.modules[module] = idx +- self.idx.merge_public(idx) ++ for module in self.modules.keys(): ++ parser = CParser(module) ++ idx = parser.parse() ++ # idx.analyze() ++ self.modules[module] = idx ++ self.idx.merge_public(idx) + + def scan(self): + for directory in self.directories: +- files = glob.glob(directory + "/*.c") +- for file in files: +- skip = 0 +- for excl in self.excludes: +- if string.find(file, excl) != -1: +- skip = 1; +- break +- if skip == 0: +- self.modules[file] = None; +- files = glob.glob(directory + "/*.h") +- for file in files: +- skip = 0 +- for excl in self.excludes: +- if string.find(file, excl) != -1: +- skip = 1; +- break +- if skip == 0: +- self.headers[file] = None; +- self.scanHeaders() +- self.scanModules() ++ files = glob.glob(directory + "/*.c") ++ for file in files: ++ skip = 0 ++ for excl in self.excludes: ++ if string.find(file, excl) != -1: ++ skip = 1; ++ break ++ if skip == 0: ++ self.modules[file] = None; ++ files = glob.glob(directory + "/*.h") ++ for file in files: ++ skip = 0 ++ for excl in self.excludes: ++ if string.find(file, excl) != -1: ++ skip = 1; ++ break ++ if skip == 0: ++ self.headers[file] = None; ++ self.scanHeaders() ++ self.scanModules() + + def modulename_file(self, file): + module = os.path.basename(file) +- if module[-2:] == '.h': +- module = module[:-2] +- return module ++ if module[-2:] == '.h': ++ module = module[:-2] ++ return module + + def serialize_enum(self, output, name): + id = self.idx.enums[name] + output.write(" \n") + + def serialize_macro(self, output, name): + id = self.idx.macros[name] + output.write(" \n" % (name, +- self.modulename_file(id.module))) +- if id.info != None: ++ self.modulename_file(id.module))) ++ if id.info != None: + try: +- (args, desc) = id.info +- if desc != None and desc != "": +- output.write(" %s\n" % (escape(desc))) +- self.indexString(name, desc) +- for arg in args: +- (name, desc) = arg +- if desc != None and desc != "": +- output.write(" \n" % ( +- name, escape(desc))) +- self.indexString(name, desc) +- else: +- output.write(" \n" % (name)) ++ (args, desc) = id.info ++ if desc != None and desc != "": ++ output.write(" %s\n" % (escape(desc))) ++ self.indexString(name, desc) ++ for arg in args: ++ (name, desc) = arg ++ if desc != None and desc != "": ++ output.write(" \n" % ( ++ name, escape(desc))) ++ self.indexString(name, desc) ++ else: ++ output.write(" \n" % (name)) + except: + pass + output.write(" \n") + + def serialize_typedef(self, output, name): + id = self.idx.typedefs[name] +- if id.info[0:7] == 'struct ': +- output.write(" \n"); +- try: +- for field in self.idx.structs[name].info: +- desc = field[2] +- self.indexString(name, desc) +- if desc == None: +- desc = '' +- else: +- desc = escape(desc) +- output.write(" \n" % (field[1] , field[0], desc)) +- except: +- print "Failed to serialize struct %s" % (name) +- output.write(" \n") +- else: +- output.write("/>\n"); +- else : +- output.write(" \n" % ( +- name, self.modulename_file(id.module), id.info)) ++ if id.info[0:7] == 'struct ': ++ output.write(" \n"); ++ try: ++ for field in self.idx.structs[name].info: ++ desc = field[2] ++ self.indexString(name, desc) ++ if desc == None: ++ desc = '' ++ else: ++ desc = escape(desc) ++ output.write(" \n" % (field[1] , field[0], desc)) ++ except: ++ print("Failed to serialize struct %s" % (name)) ++ output.write(" \n") ++ else: ++ output.write("/>\n"); ++ else : ++ output.write(" \n" % ( ++ name, self.modulename_file(id.module), id.info)) + + def serialize_variable(self, output, name): + id = self.idx.variables[name] +- if id.info != None: +- output.write(" \n" % ( +- name, self.modulename_file(id.module), id.info)) +- else: +- output.write(" \n" % ( +- name, self.modulename_file(id.module))) +- ++ if id.info != None: ++ output.write(" \n" % ( ++ name, self.modulename_file(id.module), id.info)) ++ else: ++ output.write(" \n" % ( ++ name, self.modulename_file(id.module))) ++ + def serialize_function(self, output, name): + id = self.idx.functions[name] +- if name == debugsym: +- print "=>", id ++ if name == debugsym: ++ print("=>", id) + + output.write(" <%s name='%s' file='%s'>\n" % (id.type, name, +- self.modulename_file(id.module))) +- if id.conditionals != None: +- for cond in id.conditionals: +- output.write(" %s\n"% (cond)); +- try: +- (ret, params, desc) = id.info +- output.write(" %s\n" % (escape(desc))) +- self.indexString(name, desc) +- if ret[0] != None: +- if ret[0] == "void": +- output.write(" \n") +- else: +- output.write(" \n" % ( +- ret[0], escape(ret[1]))) +- self.indexString(name, ret[1]) +- for param in params: +- if param[0] == 'void': +- continue +- if param[2] == None: +- output.write(" \n" % (param[1], param[0])) +- else: +- output.write(" \n" % (param[1], param[0], escape(param[2]))) +- self.indexString(name, param[2]) +- except: +- print "Failed to save function %s info: " % name, `id.info` ++ self.modulename_file(id.module))) ++ if id.conditionals != None: ++ for cond in id.conditionals: ++ output.write(" %s\n"% (cond)); ++ try: ++ (ret, params, desc) = id.info ++ output.write(" %s\n" % (escape(desc))) ++ self.indexString(name, desc) ++ if ret[0] != None: ++ if ret[0] == "void": ++ output.write(" \n") ++ else: ++ output.write(" \n" % ( ++ ret[0], escape(ret[1]))) ++ self.indexString(name, ret[1]) ++ for param in params: ++ if param[0] == 'void': ++ continue ++ if param[2] == None: ++ output.write(" \n" % (param[1], param[0])) ++ else: ++ output.write(" \n" % (param[1], param[0], escape(param[2]))) ++ self.indexString(name, param[2]) ++ except: ++ print("Failed to save function %s info: " % name, id.info) + output.write(" \n" % (id.type)) + + def serialize_exports(self, output, file): + module = self.modulename_file(file) +- output.write(" \n" % (module)) +- dict = self.headers[file] +- if dict.info != None: +- for data in ('Summary', 'Description', 'Author'): +- try: +- output.write(" <%s>%s\n" % ( +- string.lower(data), +- escape(dict.info[data]), +- string.lower(data))) +- except: +- print "Header %s lacks a %s description" % (module, data) +- if dict.info.has_key('Description'): +- desc = dict.info['Description'] +- if string.find(desc, "DEPRECATED") != -1: +- output.write(" \n") ++ output.write(" \n" % (module)) ++ dict = self.headers[file] ++ if dict.info != None: ++ for data in ('Summary', 'Description', 'Author'): ++ try: ++ output.write(" <%s>%s\n" % ( ++ string.lower(data), ++ escape(dict.info[data]), ++ string.lower(data))) ++ except: ++ print("Header %s lacks a %s description" % (module, data)) ++ if dict.info.has_key('Description'): ++ desc = dict.info['Description'] ++ if string.find(desc, "DEPRECATED") != -1: ++ output.write(" \n") + + ids = dict.macros.keys() +- ids.sort() +- for id in uniq(ids): +- # Macros are sometime used to masquerade other types. +- if dict.functions.has_key(id): +- continue +- if dict.variables.has_key(id): +- continue +- if dict.typedefs.has_key(id): +- continue +- if dict.structs.has_key(id): +- continue +- if dict.enums.has_key(id): +- continue +- output.write(" \n" % (id)) ++ ids.sort() ++ for id in uniq(ids): ++ # Macros are sometime used to masquerade other types. ++ if dict.functions.has_key(id): ++ continue ++ if dict.variables.has_key(id): ++ continue ++ if dict.typedefs.has_key(id): ++ continue ++ if dict.structs.has_key(id): ++ continue ++ if dict.enums.has_key(id): ++ continue ++ output.write(" \n" % (id)) + ids = dict.enums.keys() +- ids.sort() +- for id in uniq(ids): +- output.write(" \n" % (id)) ++ ids.sort() ++ for id in uniq(ids): ++ output.write(" \n" % (id)) + ids = dict.typedefs.keys() +- ids.sort() +- for id in uniq(ids): +- output.write(" \n" % (id)) ++ ids.sort() ++ for id in uniq(ids): ++ output.write(" \n" % (id)) + ids = dict.structs.keys() +- ids.sort() +- for id in uniq(ids): +- output.write(" \n" % (id)) ++ ids.sort() ++ for id in uniq(ids): ++ output.write(" \n" % (id)) + ids = dict.variables.keys() +- ids.sort() +- for id in uniq(ids): +- output.write(" \n" % (id)) ++ ids.sort() ++ for id in uniq(ids): ++ output.write(" \n" % (id)) + ids = dict.functions.keys() +- ids.sort() +- for id in uniq(ids): +- output.write(" \n" % (id)) +- output.write(" \n") ++ ids.sort() ++ for id in uniq(ids): ++ output.write(" \n" % (id)) ++ output.write(" \n") + + def serialize_xrefs_files(self, output): + headers = self.headers.keys() + headers.sort() + for file in headers: +- module = self.modulename_file(file) +- output.write(" \n" % (module)) +- dict = self.headers[file] +- ids = uniq(dict.functions.keys() + dict.variables.keys() + \ +- dict.macros.keys() + dict.typedefs.keys() + \ +- dict.structs.keys() + dict.enums.keys()) +- ids.sort() +- for id in ids: +- output.write(" \n" % (id)) +- output.write(" \n") ++ module = self.modulename_file(file) ++ output.write(" \n" % (module)) ++ dict = self.headers[file] ++ ids = uniq(dict.functions.keys() + dict.variables.keys() + \ ++ dict.macros.keys() + dict.typedefs.keys() + \ ++ dict.structs.keys() + dict.enums.keys()) ++ ids.sort() ++ for id in ids: ++ output.write(" \n" % (id)) ++ output.write(" \n") + pass + + def serialize_xrefs_functions(self, output): + funcs = {} +- for name in self.idx.functions.keys(): +- id = self.idx.functions[name] +- try: +- (ret, params, desc) = id.info +- for param in params: +- if param[0] == 'void': +- continue +- if funcs.has_key(param[0]): +- funcs[param[0]].append(name) +- else: +- funcs[param[0]] = [name] +- except: +- pass +- typ = funcs.keys() +- typ.sort() +- for type in typ: +- if type == '' or type == 'void' or type == "int" or \ +- type == "char *" or type == "const char *" : +- continue +- output.write(" \n" % (type)) +- ids = funcs[type] +- ids.sort() +- pid = '' # not sure why we have dups, but get rid of them! +- for id in ids: +- if id != pid: +- output.write(" \n" % (id)) +- pid = id +- output.write(" \n") ++ for name in self.idx.functions.keys(): ++ id = self.idx.functions[name] ++ try: ++ (ret, params, desc) = id.info ++ for param in params: ++ if param[0] == 'void': ++ continue ++ if funcs.has_key(param[0]): ++ funcs[param[0]].append(name) ++ else: ++ funcs[param[0]] = [name] ++ except: ++ pass ++ typ = funcs.keys() ++ typ.sort() ++ for type in typ: ++ if type == '' or type == 'void' or type == "int" or \ ++ type == "char *" or type == "const char *" : ++ continue ++ output.write(" \n" % (type)) ++ ids = funcs[type] ++ ids.sort() ++ pid = '' # not sure why we have dups, but get rid of them! ++ for id in ids: ++ if id != pid: ++ output.write(" \n" % (id)) ++ pid = id ++ output.write(" \n") + + def serialize_xrefs_constructors(self, output): + funcs = {} +- for name in self.idx.functions.keys(): +- id = self.idx.functions[name] +- try: +- (ret, params, desc) = id.info +- if ret[0] == "void": +- continue +- if funcs.has_key(ret[0]): +- funcs[ret[0]].append(name) +- else: +- funcs[ret[0]] = [name] +- except: +- pass +- typ = funcs.keys() +- typ.sort() +- for type in typ: +- if type == '' or type == 'void' or type == "int" or \ +- type == "char *" or type == "const char *" : +- continue +- output.write(" \n" % (type)) +- ids = funcs[type] +- ids.sort() +- for id in ids: +- output.write(" \n" % (id)) +- output.write(" \n") ++ for name in self.idx.functions.keys(): ++ id = self.idx.functions[name] ++ try: ++ (ret, params, desc) = id.info ++ if ret[0] == "void": ++ continue ++ if funcs.has_key(ret[0]): ++ funcs[ret[0]].append(name) ++ else: ++ funcs[ret[0]] = [name] ++ except: ++ pass ++ typ = funcs.keys() ++ typ.sort() ++ for type in typ: ++ if type == '' or type == 'void' or type == "int" or \ ++ type == "char *" or type == "const char *" : ++ continue ++ output.write(" \n" % (type)) ++ ids = funcs[type] ++ ids.sort() ++ for id in ids: ++ output.write(" \n" % (id)) ++ output.write(" \n") + + def serialize_xrefs_alpha(self, output): +- letter = None +- ids = self.idx.identifiers.keys() +- ids.sort() +- for id in ids: +- if id[0] != letter: +- if letter != None: +- output.write(" \n") +- letter = id[0] +- output.write(" \n" % (letter)) +- output.write(" \n" % (id)) +- if letter != None: +- output.write(" \n") ++ letter = None ++ ids = self.idx.identifiers.keys() ++ ids.sort() ++ for id in ids: ++ if id[0] != letter: ++ if letter != None: ++ output.write(" \n") ++ letter = id[0] ++ output.write(" \n" % (letter)) ++ output.write(" \n" % (id)) ++ if letter != None: ++ output.write(" \n") + + def serialize_xrefs_references(self, output): + typ = self.idx.identifiers.keys() +- typ.sort() +- for id in typ: +- idf = self.idx.identifiers[id] +- module = idf.module +- output.write(" \n" % (id, +- 'html/' + self.basename + '-' + +- self.modulename_file(module) + '.html#' + +- id)) ++ typ.sort() ++ for id in typ: ++ idf = self.idx.identifiers[id] ++ module = idf.module ++ output.write(" \n" % (id, ++ 'html/' + self.basename + '-' + ++ self.modulename_file(module) + '.html#' + ++ id)) + + def serialize_xrefs_index(self, output): + index = self.xref +- typ = index.keys() +- typ.sort() +- letter = None +- count = 0 +- chunk = 0 +- chunks = [] +- for id in typ: +- if len(index[id]) > 30: +- continue +- if id[0] != letter: +- if letter == None or count > 200: +- if letter != None: +- output.write(" \n") +- output.write(" \n") +- count = 0 +- chunks.append(["chunk%s" % (chunk -1), first_letter, letter]) +- output.write(" \n" % (chunk)) +- first_letter = id[0] +- chunk = chunk + 1 +- elif letter != None: +- output.write(" \n") +- letter = id[0] +- output.write(" \n" % (letter)) +- output.write(" \n" % (id)) +- tokens = index[id]; +- tokens.sort() +- tok = None +- for token in tokens: +- if tok == token: +- continue +- tok = token +- output.write(" \n" % (token)) +- count = count + 1 +- output.write(" \n") +- if letter != None: +- output.write(" \n") +- output.write(" \n") +- if count != 0: +- chunks.append(["chunk%s" % (chunk -1), first_letter, letter]) +- output.write(" \n") +- for ch in chunks: +- output.write(" \n" % ( +- ch[0], ch[1], ch[2])) +- output.write(" \n") ++ typ = index.keys() ++ typ.sort() ++ letter = None ++ count = 0 ++ chunk = 0 ++ chunks = [] ++ for id in typ: ++ if len(index[id]) > 30: ++ continue ++ if id[0] != letter: ++ if letter == None or count > 200: ++ if letter != None: ++ output.write(" \n") ++ output.write(" \n") ++ count = 0 ++ chunks.append(["chunk%s" % (chunk -1), first_letter, letter]) ++ output.write(" \n" % (chunk)) ++ first_letter = id[0] ++ chunk = chunk + 1 ++ elif letter != None: ++ output.write(" \n") ++ letter = id[0] ++ output.write(" \n" % (letter)) ++ output.write(" \n" % (id)) ++ tokens = index[id]; ++ tokens.sort() ++ tok = None ++ for token in tokens: ++ if tok == token: ++ continue ++ tok = token ++ output.write(" \n" % (token)) ++ count = count + 1 ++ output.write(" \n") ++ if letter != None: ++ output.write(" \n") ++ output.write(" \n") ++ if count != 0: ++ chunks.append(["chunk%s" % (chunk -1), first_letter, letter]) ++ output.write(" \n") ++ for ch in chunks: ++ output.write(" \n" % ( ++ ch[0], ch[1], ch[2])) ++ output.write(" \n") + + def serialize_xrefs(self, output): +- output.write(" \n") +- self.serialize_xrefs_references(output) +- output.write(" \n") +- output.write(" \n") +- self.serialize_xrefs_alpha(output) +- output.write(" \n") +- output.write(" \n") +- self.serialize_xrefs_constructors(output) +- output.write(" \n") +- output.write(" \n") +- self.serialize_xrefs_functions(output) +- output.write(" \n") +- output.write(" \n") +- self.serialize_xrefs_files(output) +- output.write(" \n") +- output.write(" \n") +- self.serialize_xrefs_index(output) +- output.write(" \n") ++ output.write(" \n") ++ self.serialize_xrefs_references(output) ++ output.write(" \n") ++ output.write(" \n") ++ self.serialize_xrefs_alpha(output) ++ output.write(" \n") ++ output.write(" \n") ++ self.serialize_xrefs_constructors(output) ++ output.write(" \n") ++ output.write(" \n") ++ self.serialize_xrefs_functions(output) ++ output.write(" \n") ++ output.write(" \n") ++ self.serialize_xrefs_files(output) ++ output.write(" \n") ++ output.write(" \n") ++ self.serialize_xrefs_index(output) ++ output.write(" \n") + + def serialize(self): + filename = "%s-api.xml" % self.name +- print "Saving XML description %s" % (filename) ++ print("Saving XML description %s" % (filename)) + output = open(filename, "w") + output.write('\n') + output.write("\n" % self.name) +@@ -1902,7 +1902,7 @@ + output.close() + + filename = "%s-refs.xml" % self.name +- print "Saving XML Cross References %s" % (filename) ++ print("Saving XML Cross References %s" % (filename)) + output = open(filename, "w") + output.write('\n') + output.write("\n" % self.name) +@@ -1914,19 +1914,19 @@ + def rebuild(): + builder = None + if glob.glob("../libgamin/gam_api.c") != [] : +- print "Rebuilding API description for gamin" +- builder = docBuilder("gamin", ["../libgamin"]) ++ print("Rebuilding API description for gamin") ++ builder = docBuilder("gamin", ["../libgamin"]) + else: +- print "rebuild() failed, unable to guess the module" +- return None ++ print("rebuild() failed, unable to guess the module") ++ return None + builder.scan() + builder.analyze() + builder.serialize() + # if glob.glob("../libexslt/exslt.c") != [] : + # extra = docBuilder("libexslt", ["../libexslt"], ["libexslt.h"]) +-# extra.scan() +-# extra.analyze() +-# extra.serialize() ++# extra.scan() ++# extra.analyze() ++# extra.serialize() + return builder + + # +@@ -1942,4 +1942,4 @@ + debug = 1 + parse(sys.argv[1]) + else: +- rebuild() ++ rebuild() +--- a/configure.in 2020-04-28 11:48:32.720666822 +0300 ++++ b/configure.in 2020-04-28 11:50:19.631211997 +0300 +@@ -470,7 +470,7 @@ + if test -x "$PYTHON" + then + echo Found python in environment PYTHON=$PYTHON +- with_python=`$PYTHON -c "import sys; print sys.exec_prefix"` ++ with_python=`$PYTHON -c "import sys; print(sys.exec_prefix)"` + else + AC_PATH_PROG(PYTHON, python python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5) + fi +@@ -478,7 +478,7 @@ + fi + if test "$PYTHON" != "" + then +- PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"` ++ PYTHON_VERSION=`$PYTHON -c "import sys; print(sys.version[[0:3]])"` + echo Found Python version $PYTHON_VERSION + fi + if test "$PYTHON_VERSION" != "" +@@ -504,7 +504,7 @@ + fi + if test ! -d "$PYTHON_SITE_PACKAGES" + then +- PYTHON_SITE_PACKAGES=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_python_lib()"` ++ PYTHON_SITE_PACKAGES=`$PYTHON -c "from distutils import sysconfig; print(sysconfig.get_python_lib())"` + fi + fi + fi +--- a/python/gamin.c 2020-04-28 12:14:53.648815347 +0300 ++++ b/python/gamin.c 2020-04-28 17:06:40.892100767 +0300 +@@ -174,7 +174,7 @@ + + static PyObject * + gamin_Errno(PyObject *self, PyObject * args) { +- return(PyInt_FromLong(FAMErrno)); ++ return(PyLong_FromLong(FAMErrno)); + } + + static PyObject * +@@ -183,9 +183,9 @@ + + ret = fam_connect(); + if (ret < 0) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(ret)); ++ return(PyLong_FromLong(ret)); + } + + static PyObject * +@@ -198,9 +198,9 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(FAMCONNECTION_GETFD(conn))); ++ return(PyLong_FromLong(FAMCONNECTION_GETFD(conn))); + } + + static PyObject * +@@ -212,7 +212,7 @@ + return(NULL); + + ret = release_connection(no); +- return(PyInt_FromLong(ret)); ++ return(PyLong_FromLong(ret)); + } + + static PyObject * +@@ -227,16 +227,16 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + + ret = FAMNextEvent(conn, &fe); + if (ret < 0) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + call_internal_callback(fe.userdata, &fe.filename[0], fe.code); + +- return(PyInt_FromLong(ret)); ++ return(PyLong_FromLong(ret)); + } + + static PyObject * +@@ -252,23 +252,23 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + + do { + ret = FAMPending(conn); + if (ret < 0) +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + if (ret == 0) + break; + ret = FAMNextEvent(conn, &fe); + if (ret < 0) +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + call_internal_callback(fe.userdata, &fe.filename[0], fe.code); + nb++; + } while (ret >= 0); + +- return(PyInt_FromLong(nb)); ++ return(PyLong_FromLong(nb)); + } + + static PyObject * +@@ -281,9 +281,9 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(FAMPending(conn))); ++ return(PyLong_FromLong(FAMPending(conn))); + } + + static PyObject * +@@ -296,9 +296,9 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(FAMNoExists(conn))); ++ return(PyLong_FromLong(FAMNoExists(conn))); + } + + static PyObject * +@@ -317,20 +317,20 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + noreq = get_request(); + if (noreq < 0) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + request = check_request(noreq); + + ret = FAMMonitorDirectory(conn, filename, request, userdata); + if (ret < 0) { + release_request(noreq); +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(noreq)); ++ return(PyLong_FromLong(noreq)); + } + + static PyObject * +@@ -349,20 +349,20 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + noreq = get_request(); + if (noreq < 0) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + request = check_request(noreq); + + ret = FAMMonitorFile(conn, filename, request, userdata); + if (ret < 0) { + release_request(noreq); +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(noreq)); ++ return(PyLong_FromLong(noreq)); + } + + static PyObject * +@@ -379,19 +379,19 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + request = check_request(noreq); + if (request == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + + ret = FAMCancelMonitor(conn, request); + if (ret < 0) { + release_request(noreq); +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(ret)); ++ return(PyLong_FromLong(ret)); + } + + #ifdef GAMIN_DEBUG_API +@@ -411,20 +411,20 @@ + + conn = check_connection(no); + if (conn == NULL) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + noreq = get_request(); + if (noreq < 0) { +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } + request = check_request(noreq); + + ret = FAMDebug(conn, filename, request, userdata); + if (ret < 0) { + release_request(noreq); +- return(PyInt_FromLong(-1)); ++ return(PyLong_FromLong(-1)); + } +- return(PyInt_FromLong(noreq)); ++ return(PyLong_FromLong(noreq)); + } + #endif + +@@ -446,17 +446,26 @@ + {NULL, NULL, 0, NULL} + }; + +-void +-init_gamin(void) +-{ ++static struct PyModuleDef moduledef = { ++ PyModuleDef_HEAD_INIT, ++ (char *) "_gamin", ++ "Python gamin module", ++ -1, ++ gaminMethods, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++}; ++ ++PyMODINIT_FUNC PyInit__gamin(void) { + static int initialized = 0; + + if (initialized != 0) + return; + +- /* intialize the python extension module */ +- Py_InitModule((char *) "_gamin", gaminMethods); +- + initialized = 1; ++ ++ return PyModule_Create(&moduledef); + } +