fix macro expansion
[m6w6/ext-psi] / src / token.c
index 5f177c43c5d6af795f945e6bc37de9557dbb2677..18c74375fe0b84eb18cd5fadf0994e7774755762 100644 (file)
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/
 
-#include "php_psi_stdinc.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
 
 #include <ctype.h>
 
+#include <Zend/zend_smart_str.h>
+
 #include "token.h"
 #include "parser.h"
 
-size_t psi_token_alloc_size(size_t token_len, size_t fname_len) {
-       return sizeof(struct psi_token) + token_len + fname_len + 2;
-}
+#ifndef PSI_DEBUG_TOKEN_ALLOC
+#      define PSI_DEBUG_TOKEN_ALLOC 0
+#endif
 
 struct psi_token *psi_token_init(token_t token_typ, const char *token_txt,
-               size_t token_len, unsigned col, unsigned line, const char *file)
+               size_t token_len, unsigned col, unsigned line, zend_string *file)
 {
        struct psi_token *T;
-       size_t file_len = strlen(file);
 
-       T = calloc(1, psi_token_alloc_size(token_len, file_len));
+       T = pecalloc(1, sizeof(*T), 1);
        T->type = token_typ;
-       T->size = token_len;
-       T->text = &T->buf[0];
-       T->file = &T->buf[token_len + 1];
-       T->line = line;
        T->col = col;
-
-       memcpy(T->text, token_txt, token_len);
-       memcpy(T->file, file, file_len);
-
+       T->line = line;
+       T->file = zend_string_copy(file);
+       T->text = psi_string_init_interned(token_txt, token_len, 1);
+#if PSI_DEBUG_TOKEN_ALLOC
+       fprintf(stderr, "PSI: token_init %p\t", T);
+       psi_token_dump(NULL, T);
+#endif
        return T;
 }
 
 void psi_token_free(struct psi_token **token_ptr) {
        if (*token_ptr) {
                struct psi_token *token = *token_ptr;
-
+#if PSI_DEBUG_TOKEN_ALLOC
+               fprintf(stderr, "PSI: token_free %p\t", token);
+               psi_token_dump(NULL, token);
+#endif
                *token_ptr = NULL;
+               zend_string_release(token->text);
+               zend_string_release(token->file);
                free(token);
        }
 }
 
 struct psi_token *psi_token_copy(struct psi_token *src) {
-       size_t strct_len = psi_token_alloc_size(src->size, strlen(src->file));
-       struct psi_token *ptr = malloc(strct_len);
+       struct psi_token *ptr = pemalloc(sizeof(*ptr), 1);
 
-       memcpy(ptr, src, strct_len);
-
-       ptr->text = &ptr->buf[0];
-       ptr->file = &ptr->buf[ptr->size + 1];
+       *ptr = *src;
+#if PSI_DEBUG_TOKEN_ALLOC
+       fprintf(stderr, "PSI: token_copy %p\t", ptr);
+       psi_token_dump(NULL, src);
+#endif
+       ptr->text = zend_string_copy(ptr->text);
+       ptr->file = zend_string_copy(ptr->file);
 
        return ptr;
 }
@@ -79,90 +90,76 @@ void psi_token_copy_ctor(struct psi_token **tok) {
        *tok = psi_token_copy(*tok);
 }
 
+/* concatenate `argc` number of tokens separated by `sep` into a newly allocated token */
 struct psi_token *psi_token_cat(const char *sep, unsigned argc, ...) {
        va_list argv;
        unsigned i;
        size_t sep_len = sep ? strlen(sep) : 0;
-       struct psi_token *T = NULL;
+       struct psi_token *T = pemalloc(sizeof(*T), 1);
+       smart_str text = {0};
 
        va_start(argv, argc);
-       for (i = 0; i < argc; ++i) {
-               struct psi_token *arg = va_arg(argv, struct psi_token *);
 
-               if (T) {
-                       size_t token_len = T->size, fname_len = strlen(T->file);
-                       struct psi_token *tmp = realloc(T, psi_token_alloc_size(T->size += arg->size + sep_len, fname_len));
+       *T = *(struct psi_token *) va_arg(argv, struct psi_token *);
+       T->type = PSI_T_NAME;
+       T->file = zend_string_copy(T->file);
 
-                       if (tmp) {
-                               T = tmp;
-                       } else {
-                               free(T);
-                               va_end(argv);
-                               return NULL;
-                       }
+       smart_str_append_ex(&text, T->text, 1);
 
-                       T->text = &T->buf[0];
-                       T->file = &T->buf[T->size + 1];
-                       memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
-                       memcpy(&T->buf[token_len], sep, sep_len);
-                       memcpy(&T->buf[token_len + sep_len], arg->text, arg->size + 1);
-               } else {
-                       T = psi_token_copy(arg);
-                       T->type = PSI_T_NAME;
-               }
+       for (i = 1; i < argc; ++i) {
+               struct psi_token *arg = va_arg(argv, struct psi_token *);
+
+               smart_str_appendl_ex(&text, sep, sep_len, 1);
+               smart_str_append_ex(&text, arg->text, 1);
        }
        va_end(argv);
 
+       T->text = smart_str_extract(&text);
+
+#if PSI_DEBUG_TOKEN_ALLOC
+       fprintf(stderr, "PSI: token_cat  %p\n", T);
+#endif
        return T;
 }
 
-struct psi_token *psi_token_prepend(const char *sep, struct psi_token *T, unsigned argc, ...) {
+/* append `argc` number of C strings separated by `sep` to token `T` */
+struct psi_token *psi_token_append(const char *sep, struct psi_token *T, unsigned argc, ...) {
        va_list argv;
        unsigned i;
        size_t sep_len = sep ? strlen(sep) : 0;
+       smart_str text = {0};
+
+       smart_str_append_ex(&text, T->text, 1);
 
        va_start(argv, argc);
        for (i = 0; i < argc; ++i) {
                char *str = va_arg(argv, char *);
-               size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
-
-               T = realloc(T, psi_token_alloc_size(T->size += str_len + sep_len, fname_len));
-               T->text = &T->buf[0];
-               T->file = &T->buf[T->size + 1];
-               memmove(&T->buf[str_len + sep_len], &T->buf[0], token_len + 1 + fname_len + 1);
-               memcpy(&T->buf[0], str, str_len);
-               memcpy(&T->buf[str_len], sep, sep_len);
-               T->buf[T->size] = '\0';
-       }
-       va_end(argv);
+               size_t str_len = strlen(str);
 
-       return T;
-}
-struct psi_token *psi_token_append(const char *sep, struct psi_token *T, unsigned argc, ...) {
-       va_list argv;
-       unsigned i;
-       size_t sep_len = sep ? strlen(sep) : 0;
+               if (sep_len && text.a) {
+                       smart_str_appendl_ex(&text, sep, sep_len, 1);
+               }
 
-       va_start(argv, argc);
-       for (i = 0; i < argc; ++i) {
-               char *str = va_arg(argv, char *);
-               size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
-
-               T = realloc(T, psi_token_alloc_size(T->size += str_len + sep_len, fname_len));
-               T->text = &T->buf[0];
-               T->file = &T->buf[T->size + 1];
-               memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
-               memcpy(&T->buf[token_len], sep, sep_len);
-               memcpy(&T->buf[token_len + sep_len], str, str_len + 1);
+               smart_str_appendl_ex(&text, str, str_len, 1);
        }
        va_end(argv);
 
+       zend_string_release(T->text);
+       T->text = smart_str_extract(&text);
+
        return T;
 }
 
 char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen);
 struct psi_token *psi_token_translit(struct psi_token *T, char *from, char *to) {
-       php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
+       zend_string *tmp = zend_string_init(T->text->val, T->text->len, 1);
+
+       zend_string_release(T->text);
+       T->text = tmp;
+
+       php_strtr(T->text->val, T->text->len, from, to, MIN(strlen(from), strlen(to)));
+       zend_string_forget_hash_val(T->text);
+
        return T;
 }
 
@@ -192,57 +189,62 @@ uint64_t psi_token_hash(struct psi_token *t, char *digest_buf) {
        char loc_buf[48];
 
        sprintf(loc_buf, "%u%u", t->line, t->col);
-       return psi_hash(digest_buf, t->file, loc_buf, (char *) NULL);
+       return psi_hash(digest_buf, t->file->val, loc_buf, (char *) NULL);
 }
 
-void psi_token_dump(int fd, struct psi_token *t)
+void psi_token_dump(struct psi_dump *dump, struct psi_token *t)
 {
        size_t i;
 
-       dprintf(fd, "TOKEN %p (%d) ", t, t->type);
+       if (!t) {
+               PSI_DUMP(dump, "TOKEN deleted\n");
+               return;
+       }
+
+       PSI_DUMP(dump, "TOKEN %p (%u) ", t, t->type);
        if (t->type == PSI_T_EOF) {
-               dprintf(fd, "EOF");
+               PSI_DUMP(dump, "EOF");
        } else {
-               dprintf(fd, "\"");
-               for (i = 0; i < t->size; ++i) {
-                       switch (t->text[i]) {
+               PSI_DUMP(dump, "\"");
+               for (i = 0; i < t->text->len; ++i) {
+                       switch (t->text->val[i]) {
                        case '\0':
-                               dprintf(fd, "\\0");
+                               PSI_DUMP(dump, "\\0");
                                break;
                        case '\a':
-                               dprintf(fd, "\\a");
+                               PSI_DUMP(dump, "\\a");
                                break;
                        case '\b':
-                               dprintf(fd, "\\b");
+                               PSI_DUMP(dump, "\\b");
                                break;
                        case '\f':
-                               dprintf(fd, "\\f");
+                               PSI_DUMP(dump, "\\f");
                                break;
                        case '\n':
-                               dprintf(fd, "\\n");
+                               PSI_DUMP(dump, "\\n");
                                break;
                        case '\r':
-                               dprintf(fd, "\\r");
+                               PSI_DUMP(dump, "\\r");
                                break;
                        case '\t':
-                               dprintf(fd, "\\t");
+                               PSI_DUMP(dump, "\\t");
                                break;
                        case '\v':
-                               dprintf(fd, "\\v");
+                               PSI_DUMP(dump, "\\v");
                                break;
                        case '"':
-                               dprintf(fd, "\\\"");
+                               PSI_DUMP(dump, "\\\"");
                                break;
                        default:
-                               if (isprint(t->text[i])) {
-                                       dprintf(fd, "%c", t->text[i]);
+                               if (isprint(t->text->val[i])) {
+                                       PSI_DUMP(dump, "%c", t->text->val[i]);
                                } else {
-                                       dprintf(fd, "\\x%02hhX", t->text[i]);
+                                       PSI_DUMP(dump, "\\x%02hhX", t->text->val[i]);
                                }
                                break;
                        }
                }
-               dprintf(fd, "\"");
+               PSI_DUMP(dump, "\"");
        }
-       dprintf(fd, " at col %u in %s on line %u\n", t->col, t->file, t->line);
+       PSI_DUMP(dump, " at col %u in %s on line %u\n", t->col, t->file->val, t->line);
 }