+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 fname_len = strlen(T->file);
+
+ T = realloc(T, PSI_TokenAllocSize(T->size + arg->size, fname_len));
+ memmove(&T->buf[T->size + 1], T->file, fname_len + 1);
+ memcpy(T->file - 1, arg->text, arg->size + 1);
+ T->file = &T->buf[T->size + 1];
+ } else {
+ T = PSI_TokenCopy(arg);
+ T->type = PSI_T_NAME;
+ }
+ }
+ va_end(argv);
+
+ return T;
+}
+
+static inline const char *PSI_TokenLocation(PSI_Token *t) {
+ return t ? t->file : "<builtin>:0:0";
+}
+