+ memcpy(T->file, P->psi.file.fn, fname_len);
+
+ return T;
+}
+
+static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) {
+ size_t strct_len = PSI_TokenAllocSize(src->size, strlen(src->file));
+ PSI_Token *ptr = malloc(strct_len);
+
+ memcpy(ptr, src, strct_len);
+
+ ptr->text = &ptr->buf[0];
+ ptr->file = &ptr->buf[ptr->size + 1];
+
+ return ptr;
+}
+
+static inline PSI_Token *PSI_TokenCat(unsigned argc, ...) {
+ va_list argv;
+ unsigned i;
+ PSI_Token *T = NULL;
+
+ va_start(argv, argc);
+ for (i = 0; i < argc; ++i) {
+ PSI_Token *arg = va_arg(argv, PSI_Token *);
+
+ if (T) {
+ size_t token_len = T->size, fname_len = strlen(T->file);
+
+ T = realloc(T, PSI_TokenAllocSize(T->size += arg->size + 1, fname_len));
+ T->text = &T->buf[0];
+ T->file = &T->buf[T->size + 1];
+ T->buf[token_len] = ' ';
+ memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
+ memcpy(&T->buf[token_len + 1], arg->text, arg->size + 1);
+ } else {
+ T = PSI_TokenCopy(arg);
+ T->type = PSI_T_NAME;
+ }
+ }
+ va_end(argv);
+
+ return T;
+}
+
+static inline PSI_Token *PSI_TokenAppend(PSI_Token *T, unsigned argc, ...) {
+ va_list argv;
+ unsigned i;
+
+ 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_TokenAllocSize(T->size += str_len + 1, fname_len));
+ T->text = &T->buf[0];
+ T->file = &T->buf[T->size + 1];
+ T->buf[token_len] = ' ';
+ memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
+ memcpy(&T->buf[token_len + 1], str, str_len + 1);
+ }
+ va_end(argv);
+
+ return T;
+}