a9675f8eaed50e34c9bd25623f61e9459c0fd92b
[m6w6/ext-psi] / src / token.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #else
4 # include "php_config.h"
5 #endif
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <inttypes.h>
11 #include <sys/param.h>
12
13 #include "parser_proc.h"
14 #include "token.h"
15 #include "parser.h"
16
17 size_t psi_token_alloc_size(size_t token_len, size_t fname_len) {
18 return sizeof(struct psi_token) + token_len + fname_len + 2;
19 }
20
21 struct psi_token *psi_token_alloc(struct psi_parser *P) {
22 struct psi_token *T;
23 size_t token_len, fname_len;
24 token_t token_typ;
25
26 if (P->cur < P->tok) {
27 return NULL;
28 }
29
30 token_typ = P->num;
31 token_len = P->cur - P->tok;
32 fname_len = strlen(P->psi.file.fn);
33
34 T = calloc(1, psi_token_alloc_size(token_len, fname_len));
35 T->type = token_typ;
36 T->size = token_len;
37 T->text = &T->buf[0];
38 T->file = &T->buf[token_len + 1];
39 T->line = P->line;
40 T->col = P->col;
41
42 memcpy(T->text, P->tok, token_len);
43 memcpy(T->file, P->psi.file.fn, fname_len);
44
45 return T;
46 }
47
48 struct psi_token *psi_token_copy(struct psi_token *src) {
49 size_t strct_len = psi_token_alloc_size(src->size, strlen(src->file));
50 struct psi_token *ptr = malloc(strct_len);
51
52 memcpy(ptr, src, strct_len);
53
54 ptr->text = &ptr->buf[0];
55 ptr->file = &ptr->buf[ptr->size + 1];
56
57 return ptr;
58 }
59
60 struct psi_token *psi_token_cat(unsigned argc, ...) {
61 va_list argv;
62 unsigned i;
63 struct psi_token *T = NULL;
64
65 va_start(argv, argc);
66 for (i = 0; i < argc; ++i) {
67 struct psi_token *arg = va_arg(argv, struct psi_token *);
68
69 if (T) {
70 size_t token_len = T->size, fname_len = strlen(T->file);
71
72 T = realloc(T, psi_token_alloc_size(T->size += arg->size + 1, fname_len));
73 T->text = &T->buf[0];
74 T->file = &T->buf[T->size + 1];
75 T->buf[token_len] = ' ';
76 memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
77 memcpy(&T->buf[token_len + 1], arg->text, arg->size + 1);
78 } else {
79 T = psi_token_copy(arg);
80 T->type = PSI_T_NAME;
81 }
82 }
83 va_end(argv);
84
85 return T;
86 }
87
88 struct psi_token *psi_token_append(struct psi_token *T, unsigned argc, ...) {
89 va_list argv;
90 unsigned i;
91
92 va_start(argv, argc);
93 for (i = 0; i < argc; ++i) {
94 char *str = va_arg(argv, char *);
95 size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
96
97 T = realloc(T, psi_token_alloc_size(T->size += str_len + 1, fname_len));
98 T->text = &T->buf[0];
99 T->file = &T->buf[T->size + 1];
100 T->buf[token_len] = ' ';
101 memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
102 memcpy(&T->buf[token_len + 1], str, str_len + 1);
103 }
104 va_end(argv);
105
106 return T;
107 }
108
109 char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen);
110 struct psi_token *psi_token_translit(struct psi_token *T, char *from, char *to) {
111 php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
112 return T;
113 }
114
115 static inline uint64_t psi_hash(char *digest_buf, ...)
116 {
117 uint64_t hash = 5381;
118 uint8_t c;
119 const uint8_t *ptr;
120 va_list argv;
121
122 va_start(argv, digest_buf);
123 while ((ptr = va_arg(argv, const uint8_t *))) {
124 while ((c = *ptr++)) {
125 hash = ((hash << 5) + hash) + c;
126 }
127 }
128 va_end(argv);
129
130 if (digest_buf) {
131 sprintf(digest_buf, "%" PRIx64, hash);
132 }
133
134 return hash;
135 }
136
137 uint64_t psi_token_hash(struct psi_token *t, char *digest_buf) {
138 char loc_buf[48];
139
140 sprintf(loc_buf, "%u%u", t->line, t->col);
141 return psi_hash(digest_buf, t->file, loc_buf, NULL);
142 }