If a low and high range limit has been specified, all atoms are
retrieved at once. This is also the reason why malloc() is used:
All cookies are stored before collecting the data.

By using chunks it is possible to specify a huge range or even
all possible atoms without running out of memory.

Signed-off-by: Tobias Stoeckmann <tob...@stoeckmann.org>
---
 xlsatoms.c | 51 ++++++++++++++-------------------------------------
 1 file changed, 14 insertions(+), 37 deletions(-)

diff --git a/xlsatoms.c b/xlsatoms.c
index 5bed0cc..a971901 100644
--- a/xlsatoms.c
+++ b/xlsatoms.c
@@ -234,7 +234,7 @@ do_range(xcb_connection_t *c, const char *format, char 
*range)
 }
 
 static int
-say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t 
*cookie, xcb_atom_t low, long count)
+say_batch(xcb_connection_t *c, const char *format, xcb_get_atom_name_cookie_t 
*cookie, xcb_atom_t low, long count, int stop_error)
 {
     xcb_generic_error_t *e;
     char atom_name[1024];
@@ -248,7 +248,7 @@ say_batch(xcb_connection_t *c, const char *format, 
xcb_get_atom_name_cookie_t *c
        xcb_get_atom_name_reply_t *r;
        r = xcb_get_atom_name_reply(c, cookie[i], &e);
        if (r) {
-           if (!done) {
+           if (!done || !stop_error) {
                /* We could just use %.*s in 'format', but we want to be 
compatible
                   with legacy command line usage */
                snprintf(atom_name, sizeof(atom_name), "%.*s",
@@ -265,50 +265,27 @@ say_batch(xcb_connection_t *c, const char *format, 
xcb_get_atom_name_cookie_t *c
        }
     }
 
-    return done;
+    return done && stop_error;
 }
 
 static void
 list_atoms(xcb_connection_t *c, const char *format, int mask, xcb_atom_t low, 
xcb_atom_t high)
 {
-    xcb_get_atom_name_cookie_t *cookie_jar;
+    xcb_get_atom_name_cookie_t cookie_jar[ATOMS_PER_BATCH];
     int done = 0;
+    long count;
 
-    switch (mask) {
-      case RangeHigh:
+    if ((mask & RangeLow) == 0)
        low = 1;
-       /* fall through */
-      case (RangeLow | RangeHigh):
-       if (high - low >= SIZE_MAX / sizeof(xcb_get_atom_name_cookie_t)) {
-           fprintf(stderr, "Cannot allocate space for %lu atom requests\n", 
(unsigned long) (high - low));
-           return;
-       }
-       cookie_jar = malloc((high - low + 1) * 
sizeof(xcb_get_atom_name_cookie_t));
-        if (!cookie_jar) {
-           fprintf(stderr, "Out of memory allocating space for %lu atom 
requests\n", (unsigned long) (high - low));
-           return;
-       }
+    if ((mask & RangeHigh) == 0)
+       high = UINT32_MAX;
 
-       say_batch(c, format, cookie_jar, low, high - low + 1);
-       free(cookie_jar);
-       break;
-
-      default:
-       low = 1;
-       /* fall through */
-      case RangeLow:
-       cookie_jar = malloc(ATOMS_PER_BATCH * 
sizeof(xcb_get_atom_name_cookie_t));
-        if (!cookie_jar) {
-           fprintf(stderr, "Out of memory allocating space for %ld atom 
requests\n", (long) ATOMS_PER_BATCH);
-           return;
-       }
-       while (!done) {
-           done = say_batch(c, format, cookie_jar, low, ATOMS_PER_BATCH);
-           low += ATOMS_PER_BATCH;
+    while (!done) {
+       count = high - low < ATOMS_PER_BATCH - 1 ? high - low + 1 : 
ATOMS_PER_BATCH;
+       done = say_batch(c, format, cookie_jar, low, count, (mask & RangeHigh) 
== 0);
+       if (high - low < UINT32_MAX && low == high - count + 1) {
+           done = 1;
        }
-       free(cookie_jar);
-       break;
+       low += count;
     }
-
-    return;
 }
-- 
2.18.0

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to