-__must_check __malloc char *s_a_r(const char *src, const char* macro_name,
- const char *replacement)
-{
- regex_t preg;
- size_t nmatch = 1;
- regmatch_t pmatch[1];
- int eflags = 0;
- char *dest = NULL;
- const char *bufptr = src;
-
- if (!macro_name || !replacement || !src)
- return para_strdup(src);
- regcomp(&preg, macro_name, 0);
- while (regexec(&preg, bufptr, nmatch, pmatch, eflags)
- != REG_NOMATCH) {
- char *tmp, *arg, *o_bracket, *c_bracket;
-
- o_bracket = strchr(bufptr + pmatch[0].rm_so, '(');
- c_bracket = o_bracket? strchr(o_bracket, ')') : NULL;
- if (!c_bracket)
- goto out;
- tmp = para_strdup(bufptr);
- tmp[pmatch[0].rm_so] = '\0';
- dest = para_strcat(dest, tmp);
- free(tmp);
-
- arg = para_strdup(o_bracket + 1);
- arg[c_bracket - o_bracket - 1] = '\0';
- tmp = make_message(replacement, arg);
- free(arg);
- dest = para_strcat(dest, tmp);
- free(tmp);
- bufptr = c_bracket;
- bufptr++;
+int for_each_line(unsigned flags, char *buf, size_t size,
+ line_handler_t *line_handler, void *private_data)
+{
+ char *start = buf, *end;
+ int ret, i, num_lines = 0;
+
+// PARA_NOTICE_LOG("buf: %s\n", buf);
+ while (start < buf + size) {
+ char *next_null;
+ char *next_cr;
+
+ next_cr = memchr(start, '\n', buf + size - start);
+ next_null = memchr(start, '\0', next_cr?
+ next_cr - start : buf + size - start);
+ if (!next_cr && !next_null)
+ break;
+ if (next_null)
+ end = next_null;
+ else
+ end = next_cr;
+ num_lines++;
+ if (!(flags & FELF_DISCARD_FIRST) || start != buf) {
+ if (flags & FELF_READ_ONLY) {
+ size_t s = end - start;
+ char *b = para_malloc(s + 1);
+ memcpy(b, start, s);
+ b[s] = '\0';
+ ret = line_handler(b, private_data);
+ free(b);
+ } else {
+ *end = '\0';
+ ret = line_handler(start, private_data);
+ }
+ if (ret < 0)
+ return ret;
+ }
+ start = ++end;
+ }
+ i = buf + size - start;
+ if (i && i != size && !(flags & FELF_READ_ONLY))
+ memmove(buf, start, i);
+ return i;
+}
+
+/** Return the hex characters of the lower 4 bits. */
+#define hex(a) (hexchar[(a) & 15])
+
+static void write_size_header(char *buf, int n)
+{
+ static char hexchar[] = "0123456789abcdef";
+
+ buf[0] = hex(n >> 12);
+ buf[1] = hex(n >> 8);
+ buf[2] = hex(n >> 4);
+ buf[3] = hex(n);
+ buf[4] = ' ';
+}
+
+/**
+ * Read a four-byte hex-number and return its value.
+ *
+ * Each status item sent by para_server is prefixed with such a hex number in
+ * ASCII which describes the size of the status item.
+ *
+ * \param buf The buffer which must be at least four bytes long.
+ *
+ * \return The value of the hex number on success, \p -E_SIZE_PREFIX if the
+ * buffer did not contain only hex digits.
+ */
+int read_size_header(const char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0; i < 4; i++) {
+ unsigned char c = buf[i];
+ len <<= 4;
+ if (c >= '0' && c <= '9') {
+ len += c - '0';
+ continue;
+ }
+ if (c >= 'a' && c <= 'f') {
+ len += c - 'a' + 10;
+ continue;
+ }
+ return -E_SIZE_PREFIX;
+ }
+ if (buf[4] != ' ')
+ return -E_SIZE_PREFIX;
+ return len;
+}
+
+/**
+ * Safely print into a buffer at a given offset.
+ *
+ * \param b Determines the buffer, its size, and the offset.
+ * \param fmt The format string.
+ *
+ * This function prints into the buffer given by \a b at the offset which is
+ * also given by \a b. If there is not enough space to hold the result, the
+ * buffer size is doubled until the underlying call to vsnprintf() succeeds
+ * or the size of the buffer exceeds the maximal size specified in \a b.
+ *
+ * In the latter case the unmodified \a buf and \a offset values as well as the
+ * private_data pointer of \a b are passed to the \a max_size_handler of \a b.
+ * If this function succeeds, i.e. returns a non-negative value, the offset of
+ * \a b is reset to zero and the given data is written to the beginning of the
+ * buffer. If \a max_size_handler() returns a negative value, this value is
+ * returned by \a para_printf().
+ *
+ * Upon return, the offset of \a b is adjusted accordingly so that subsequent
+ * calls to this function append data to what is already contained in the
+ * buffer.
+ *
+ * It's OK to call this function with \p b->buf being \p NULL. In this case, an
+ * initial buffer is allocated.
+ *
+ * \return The number of bytes printed into the buffer (not including the
+ * terminating \p NULL byte) on success, negative on errors. If there is no
+ * size-bound on \a b, i.e. if \p b->max_size is zero, this function never
+ * fails.
+ *
+ * \sa make_message(), vsnprintf(3).
+ */
+__printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...)
+{
+ int ret, sz_off = (b->flags & PBF_SIZE_PREFIX)? 5 : 0;
+
+ if (!b->buf) {
+ b->buf = para_malloc(128);
+ b->size = 128;
+ b->offset = 0;
+ }
+ while (1) {
+ char *p = b->buf + b->offset;
+ size_t size = b->size - b->offset;
+ va_list ap;
+
+ if (size > sz_off) {
+ va_start(ap, fmt);
+ ret = vsnprintf(p + sz_off, size - sz_off, fmt, ap);
+ va_end(ap);
+ if (ret > -1 && ret < size - sz_off) { /* success */
+ b->offset += ret + sz_off;
+ if (sz_off)
+ write_size_header(p, ret);
+ return ret + sz_off;
+ }
+ }
+ /* check if we may grow the buffer */
+ if (!b->max_size || 2 * b->size < b->max_size) { /* yes */
+ /* try again with more space */
+ b->size *= 2;
+ b->buf = para_realloc(b->buf, b->size);
+ continue;
+ }
+ /* can't grow buffer */
+ if (!b->offset || !b->max_size_handler) /* message too large */
+ return -ERRNO_TO_PARA_ERROR(ENOSPC);
+ ret = b->max_size_handler(b->buf, b->offset, b->private_data);
+ if (ret < 0)
+ return ret;
+ b->offset = 0;