From 52a6e57bfd7f273fc754c12a44eb94200f3de0b9 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Wed, 4 Jul 2018 15:29:58 +0200 Subject: Always use chunks when retrieving atoms. 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 Signed-off-by: Alan Coopersmith --- 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; } -- cgit v1.2.3