YAZ 5.35.1
utilities.c
Go to the documentation of this file.
1
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include "header.h"
7
8#define unless(C) if(!(C))
9
10#define CREATE_SIZE 1
11
12extern symbol *
14{
15 symbol *p;
16 void *mem = malloc (HEAD + (CREATE_SIZE + 1) * sizeof (symbol));
17 if (mem == NULL)
18 return NULL;
19 p = (symbol *) (HEAD + (char *) mem);
22 return p;
23}
24
25extern void
27{
28 if (p == NULL)
29 return;
30 free ((char *) p - HEAD);
31}
32
33/*
34 new_p = skip_utf8(p, c, lb, l, n); skips n characters forwards from p + c
35 if n +ve, or n characters backwards from p + c - 1 if n -ve. new_p is the new
36 position, or 0 on failure.
37
38 -- used to implement hop and next in the utf8 case.
39*/
40
41extern int
42skip_utf8 (const symbol *p, int c, int lb, int l, int n)
43{
44 int b;
45 if (n >= 0)
46 {
47 for (; n > 0; n--)
48 {
49 if (c >= l)
50 return -1;
51 b = p[c++];
52 if (b >= 0xC0)
53 { /* 1100 0000 */
54 while (c < l)
55 {
56 b = p[c];
57 if (b >= 0xC0 || b < 0x80)
58 break;
59 /* break unless b is 10------ */
60 c++;
61 }
62 }
63 }
64 }
65 else
66 {
67 for (; n < 0; n++)
68 {
69 if (c <= lb)
70 return -1;
71 b = p[--c];
72 if (b >= 0x80)
73 { /* 1000 0000 */
74 while (c > lb)
75 {
76 b = p[c];
77 if (b >= 0xC0)
78 break; /* 1100 0000 */
79 c--;
80 }
81 }
82 }
83 }
84 return c;
85}
86
87/* Code for character groupings: utf8 cases */
88
89static int
90get_utf8 (const symbol *p, int c, int l, int *slot)
91{
92 int b0, b1;
93 if (c >= l)
94 return 0;
95 b0 = p[c++];
96 if (b0 < 0xC0 || c == l)
97 { /* 1100 0000 */
98 *slot = b0;
99 return 1;
100 }
101 b1 = p[c++];
102 if (b0 < 0xE0 || c == l)
103 { /* 1110 0000 */
104 *slot = (b0 & 0x1F) << 6 | (b1 & 0x3F);
105 return 2;
106 }
107 *slot = (b0 & 0xF) << 12 | (b1 & 0x3F) << 6 | (p[c] & 0x3F);
108 return 3;
109}
110
111static int
112get_b_utf8 (const symbol *p, int c, int lb, int *slot)
113{
114 int b0, b1;
115 if (c <= lb)
116 return 0;
117 b0 = p[--c];
118 if (b0 < 0x80 || c == lb)
119 { /* 1000 0000 */
120 *slot = b0;
121 return 1;
122 }
123 b1 = p[--c];
124 if (b1 >= 0xC0 || c == lb)
125 { /* 1100 0000 */
126 *slot = (b1 & 0x1F) << 6 | (b0 & 0x3F);
127 return 2;
128 }
129 *slot = (p[c] & 0xF) << 12 | (b1 & 0x3F) << 6 | (b0 & 0x3F);
130 return 3;
131}
132
133extern int
134in_grouping_U (struct SN_env *z, const unsigned char *s, int min, int max,
135 int repeat)
136{
137 do
138 {
139 int ch;
140 int w = get_utf8 (z->p, z->c, z->l, &ch);
141 unless (w) return -1;
142 if (ch > max || (ch -= min) < 0
143 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
144 return w;
145 z->c += w;
146 }
147 while (repeat);
148 return 0;
149}
150
151extern int
152in_grouping_b_U (struct SN_env *z, const unsigned char *s, int min, int max,
153 int repeat)
154{
155 do
156 {
157 int ch;
158 int w = get_b_utf8 (z->p, z->c, z->lb, &ch);
159 unless (w) return -1;
160 if (ch > max || (ch -= min) < 0
161 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
162 return w;
163 z->c -= w;
164 }
165 while (repeat);
166 return 0;
167}
168
169extern int
170out_grouping_U (struct SN_env *z, const unsigned char *s, int min, int max,
171 int repeat)
172{
173 do
174 {
175 int ch;
176 int w = get_utf8 (z->p, z->c, z->l, &ch);
177 unless (w) return -1;
178 unless (ch > max || (ch -= min) < 0
179 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return w;
180 z->c += w;
181 }
182 while (repeat);
183 return 0;
184}
185
186extern int
187out_grouping_b_U (struct SN_env *z, const unsigned char *s, int min, int max,
188 int repeat)
189{
190 do
191 {
192 int ch;
193 int w = get_b_utf8 (z->p, z->c, z->lb, &ch);
194 unless (w) return -1;
195 unless (ch > max || (ch -= min) < 0
196 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return w;
197 z->c -= w;
198 }
199 while (repeat);
200 return 0;
201}
202
203/* Code for character groupings: non-utf8 cases */
204
205extern int
206in_grouping (struct SN_env *z, const unsigned char *s, int min, int max,
207 int repeat)
208{
209 do
210 {
211 int ch;
212 if (z->c >= z->l)
213 return -1;
214 ch = z->p[z->c];
215 if (ch > max || (ch -= min) < 0
216 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
217 return 1;
218 z->c++;
219 }
220 while (repeat);
221 return 0;
222}
223
224extern int
225in_grouping_b (struct SN_env *z, const unsigned char *s, int min, int max,
226 int repeat)
227{
228 do
229 {
230 int ch;
231 if (z->c <= z->lb)
232 return -1;
233 ch = z->p[z->c - 1];
234 if (ch > max || (ch -= min) < 0
235 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
236 return 1;
237 z->c--;
238 }
239 while (repeat);
240 return 0;
241}
242
243extern int
244out_grouping (struct SN_env *z, const unsigned char *s, int min, int max,
245 int repeat)
246{
247 do
248 {
249 int ch;
250 if (z->c >= z->l)
251 return -1;
252 ch = z->p[z->c];
253 unless (ch > max || (ch -= min) < 0
254 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 1;
255 z->c++;
256 }
257 while (repeat);
258 return 0;
259}
260
261extern int
262out_grouping_b (struct SN_env *z, const unsigned char *s, int min, int max,
263 int repeat)
264{
265 do
266 {
267 int ch;
268 if (z->c <= z->lb)
269 return -1;
270 ch = z->p[z->c - 1];
271 unless (ch > max || (ch -= min) < 0
272 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return 1;
273 z->c--;
274 }
275 while (repeat);
276 return 0;
277}
278
279extern int
280eq_s (struct SN_env *z, int s_size, const symbol *s)
281{
282 if (z->l - z->c < s_size
283 || memcmp (z->p + z->c, s, s_size * sizeof (symbol)) != 0)
284 return 0;
285 z->c += s_size;
286 return 1;
287}
288
289extern int
290eq_s_b (struct SN_env *z, int s_size, const symbol *s)
291{
292 if (z->c - z->lb < s_size
293 || memcmp (z->p + z->c - s_size, s, s_size * sizeof (symbol)) != 0)
294 return 0;
295 z->c -= s_size;
296 return 1;
297}
298
299extern int
300eq_v (struct SN_env *z, const symbol *p)
301{
302 return eq_s (z, SIZE (p), p);
303}
304
305extern int
306eq_v_b (struct SN_env *z, const symbol *p)
307{
308 return eq_s_b (z, SIZE (p), p);
309}
310
311extern int
312find_among (struct SN_env *z, const struct among *v, int v_size)
313{
314
315 int i = 0;
316 int j = v_size;
317
318 int c = z->c;
319 int l = z->l;
320 symbol *q = z->p + c;
321
322 const struct among *w;
323
324 int common_i = 0;
325 int common_j = 0;
326
327 int first_key_inspected = 0;
328
329 while (1)
330 {
331 int k = i + ((j - i) >> 1);
332 int diff = 0;
333 int common = common_i < common_j ? common_i : common_j; /* smaller */
334 w = v + k;
335 {
336 int i2;
337 for (i2 = common; i2 < w->s_size; i2++)
338 {
339 if (c + common == l)
340 {
341 diff = -1;
342 break;
343 }
344 diff = q[common] - w->s[i2];
345 if (diff != 0)
346 break;
347 common++;
348 }
349 }
350 if (diff < 0)
351 {
352 j = k;
353 common_j = common;
354 }
355 else
356 {
357 i = k;
358 common_i = common;
359 }
360 if (j - i <= 1)
361 {
362 if (i > 0)
363 break; /* v->s has been inspected */
364 if (j == i)
365 break; /* only one item in v */
366
367 /* - but now we need to go round once more to get
368 v->s inspected. This looks messy, but is actually
369 the optimal approach. */
370
371 if (first_key_inspected)
372 break;
373 first_key_inspected = 1;
374 }
375 }
376 while (1)
377 {
378 w = v + i;
379 if (common_i >= w->s_size)
380 {
381 z->c = c + w->s_size;
382 if (w->function == 0)
383 return w->result;
384 {
385 int res = w->function (z);
386 z->c = c + w->s_size;
387 if (res)
388 return w->result;
389 }
390 }
391 i = w->substring_i;
392 if (i < 0)
393 return 0;
394 }
395}
396
397/* find_among_b is for backwards processing. Same comments apply */
398
399extern int
400find_among_b (struct SN_env *z, const struct among *v, int v_size)
401{
402
403 int i = 0;
404 int j = v_size;
405
406 int c = z->c;
407 int lb = z->lb;
408 symbol *q = z->p + c - 1;
409
410 const struct among *w;
411
412 int common_i = 0;
413 int common_j = 0;
414
415 int first_key_inspected = 0;
416
417 while (1)
418 {
419 int k = i + ((j - i) >> 1);
420 int diff = 0;
421 int common = common_i < common_j ? common_i : common_j;
422 w = v + k;
423 {
424 int i2;
425 for (i2 = w->s_size - 1 - common; i2 >= 0; i2--)
426 {
427 if (c - common == lb)
428 {
429 diff = -1;
430 break;
431 }
432 diff = q[-common] - w->s[i2];
433 if (diff != 0)
434 break;
435 common++;
436 }
437 }
438 if (diff < 0)
439 {
440 j = k;
441 common_j = common;
442 }
443 else
444 {
445 i = k;
446 common_i = common;
447 }
448 if (j - i <= 1)
449 {
450 if (i > 0)
451 break;
452 if (j == i)
453 break;
454 if (first_key_inspected)
455 break;
456 first_key_inspected = 1;
457 }
458 }
459 while (1)
460 {
461 w = v + i;
462 if (common_i >= w->s_size)
463 {
464 z->c = c - w->s_size;
465 if (w->function == 0)
466 return w->result;
467 {
468 int res = w->function (z);
469 z->c = c - w->s_size;
470 if (res)
471 return w->result;
472 }
473 }
474 i = w->substring_i;
475 if (i < 0)
476 return 0;
477 }
478}
479
480
481/* Increase the size of the buffer pointed to by p to at least n symbols.
482 * If insufficient memory, returns NULL and frees the old buffer.
483 */
484static symbol *
486{
487 symbol *q;
488 int new_size = n + 20;
489 void *mem = realloc ((char *) p - HEAD,
490 HEAD + (new_size + 1) * sizeof (symbol));
491 if (mem == NULL)
492 {
493 lose_s (p);
494 return NULL;
495 }
496 q = (symbol *) (HEAD + (char *) mem);
497 CAPACITY (q) = new_size;
498 return q;
499}
500
501/* to replace symbols between c_bra and c_ket in z->p by the
502 s_size symbols at s.
503 Returns 0 on success, -1 on error.
504 Also, frees z->p (and sets it to NULL) on error.
505*/
506extern int
507replace_s (struct SN_env *z, int c_bra, int c_ket, int s_size,
508 const symbol *s, int *adjptr)
509{
510 int adjustment;
511 int len;
512 if (z->p == NULL)
513 {
514 z->p = create_s ();
515 if (z->p == NULL)
516 return -1;
517 }
518 adjustment = s_size - (c_ket - c_bra);
519 len = SIZE (z->p);
520 if (adjustment != 0)
521 {
522 if (adjustment + len > CAPACITY (z->p))
523 {
524 z->p = increase_size (z->p, adjustment + len);
525 if (z->p == NULL)
526 return -1;
527 }
528 memmove (z->p + c_ket + adjustment,
529 z->p + c_ket, (len - c_ket) * sizeof (symbol));
530 SET_SIZE (z->p, adjustment + len);
531 z->l += adjustment;
532 if (z->c >= c_ket)
533 z->c += adjustment;
534 else if (z->c > c_bra)
535 z->c = c_bra;
536 }
537 unless (s_size == 0) memmove (z->p + c_bra, s, s_size * sizeof (symbol));
538 if (adjptr != NULL)
539 *adjptr = adjustment;
540 return 0;
541}
542
543static int
545{
546
547 if (z->bra < 0 || z->bra > z->ket || z->ket > z->l || z->p == NULL || z->l > SIZE (z->p)) /* this line could be removed */
548 {
549#if 0
550 fprintf (stderr, "faulty slice operation:\n");
551 debug (z, -1, 0);
552#endif
553 return -1;
554 }
555 return 0;
556}
557
558extern int
559slice_from_s (struct SN_env *z, int s_size, const symbol *s)
560{
561 if (slice_check (z))
562 return -1;
563 return replace_s (z, z->bra, z->ket, s_size, s, NULL);
564}
565
566extern int
567slice_from_v (struct SN_env *z, const symbol *p)
568{
569 return slice_from_s (z, SIZE (p), p);
570}
571
572extern int
573slice_del (struct SN_env *z)
574{
575 return slice_from_s (z, 0, 0);
576}
577
578extern int
579insert_s (struct SN_env *z, int bra, int ket, int s_size, const symbol *s)
580{
581 int adjustment;
582 if (replace_s (z, bra, ket, s_size, s, &adjustment))
583 return -1;
584 if (bra <= z->bra)
585 z->bra += adjustment;
586 if (bra <= z->ket)
587 z->ket += adjustment;
588 return 0;
589}
590
591extern int
592insert_v (struct SN_env *z, int bra, int ket, const symbol *p)
593{
594 int adjustment;
595 if (replace_s (z, bra, ket, SIZE (p), p, &adjustment))
596 return -1;
597 if (bra <= z->bra)
598 z->bra += adjustment;
599 if (bra <= z->ket)
600 z->ket += adjustment;
601 return 0;
602}
603
604extern symbol *
605slice_to (struct SN_env *z, symbol *p)
606{
607 if (slice_check (z))
608 {
609 lose_s (p);
610 return NULL;
611 }
612 {
613 int len = z->ket - z->bra;
614 if (CAPACITY (p) < len)
615 {
616 p = increase_size (p, len);
617 if (p == NULL)
618 return NULL;
619 }
620 memmove (p, z->p + z->bra, len * sizeof (symbol));
621 SET_SIZE (p, len);
622 }
623 return p;
624}
625
626extern symbol *
627assign_to (struct SN_env *z, symbol *p)
628{
629 int len = z->l;
630 if (CAPACITY (p) < len)
631 {
632 p = increase_size (p, len);
633 if (p == NULL)
634 return NULL;
635 }
636 memmove (p, z->p, len * sizeof (symbol));
637 SET_SIZE (p, len);
638 return p;
639}
640
641#if 0
642extern void
643debug (struct SN_env *z, int number, int line_count)
644{
645 int i;
646 int limit = SIZE (z->p);
647 /*if (number >= 0) printf("%3d (line %4d): '", number, line_count); */
648 if (number >= 0)
649 printf ("%3d (line %4d): [%d]'", number, line_count, limit);
650 for (i = 0; i <= limit; i++)
651 {
652 if (z->lb == i)
653 printf ("{");
654 if (z->bra == i)
655 printf ("[");
656 if (z->c == i)
657 printf ("|");
658 if (z->ket == i)
659 printf ("]");
660 if (z->l == i)
661 printf ("}");
662 if (i < limit)
663 {
664 int ch = z->p[i];
665 if (ch == 0)
666 ch = '#';
667 printf ("%c", ch);
668 }
669 }
670 printf ("'\n");
671}
672#endif
unsigned char symbol
Definition api.h:2
void * malloc(YYSIZE_T)
void free(void *)
#define HEAD
Definition header.h:9
#define SIZE(p)
Definition header.h:11
#define CAPACITY(p)
Definition header.h:13
void debug(struct SN_env *z, int number, int line_count)
#define SET_SIZE(p, n)
Definition header.h:12
Definition api.h:14
int lb
Definition api.h:16
symbol * p
Definition api.h:15
int ket
Definition api.h:16
int c
Definition api.h:16
int bra
Definition api.h:16
int l
Definition api.h:16
Definition header.h:16
int result
Definition header.h:19
int substring_i
Definition header.h:18
int s_size
Definition header.h:16
const symbol * s
Definition header.h:17
int(* function)(struct SN_env *)
Definition header.h:20
int insert_v(struct SN_env *z, int bra, int ket, const symbol *p)
Definition utilities.c:592
int find_among_b(struct SN_env *z, const struct among *v, int v_size)
Definition utilities.c:400
int out_grouping_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:170
#define CREATE_SIZE
Definition utilities.c:10
int insert_s(struct SN_env *z, int bra, int ket, int s_size, const symbol *s)
Definition utilities.c:579
static int slice_check(struct SN_env *z)
Definition utilities.c:544
int slice_del(struct SN_env *z)
Definition utilities.c:573
int in_grouping_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:134
int eq_v_b(struct SN_env *z, const symbol *p)
Definition utilities.c:306
int in_grouping(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:206
int eq_s(struct SN_env *z, int s_size, const symbol *s)
Definition utilities.c:280
#define unless(C)
Definition utilities.c:8
int replace_s(struct SN_env *z, int c_bra, int c_ket, int s_size, const symbol *s, int *adjptr)
Definition utilities.c:507
int eq_v(struct SN_env *z, const symbol *p)
Definition utilities.c:300
void lose_s(symbol *p)
Definition utilities.c:26
static int get_utf8(const symbol *p, int c, int l, int *slot)
Definition utilities.c:90
int out_grouping_b(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:262
int skip_utf8(const symbol *p, int c, int lb, int l, int n)
Definition utilities.c:42
int in_grouping_b_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:152
int eq_s_b(struct SN_env *z, int s_size, const symbol *s)
Definition utilities.c:290
int out_grouping(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:244
int out_grouping_b_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:187
symbol * create_s(void)
Definition utilities.c:13
symbol * slice_to(struct SN_env *z, symbol *p)
Definition utilities.c:605
int slice_from_v(struct SN_env *z, const symbol *p)
Definition utilities.c:567
int find_among(struct SN_env *z, const struct among *v, int v_size)
Definition utilities.c:312
int slice_from_s(struct SN_env *z, int s_size, const symbol *s)
Definition utilities.c:559
int in_grouping_b(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
Definition utilities.c:225
symbol * assign_to(struct SN_env *z, symbol *p)
Definition utilities.c:627
static int get_b_utf8(const symbol *p, int c, int lb, int *slot)
Definition utilities.c:112
static symbol * increase_size(symbol *p, int n)
Definition utilities.c:485