8 #define unless(C) if(!(C))
12 extern symbol
* create_s(void) {
14 void * mem
= malloc(HEAD
+ (CREATE_SIZE
+ 1) * sizeof(symbol
));
15 if (mem
== NULL
) return NULL
;
16 p
= (symbol
*) (HEAD
+ (char *) mem
);
17 CAPACITY(p
) = CREATE_SIZE
;
18 SET_SIZE(p
, CREATE_SIZE
);
22 extern void lose_s(symbol
* p
) {
23 if (p
== NULL
) return;
24 free((char *) p
- HEAD
);
28 new_p = X_skip_utf8(p, c, lb, l, n); skips n characters forwards from p + c
29 if n +ve, or n characters backwards from p +c - 1 if n -ve. new_p is the new
30 position, or 0 on failure.
32 -- used to implement hop and next in the utf8 case.
35 extern int skip_utf8(const symbol
* p
, int c
, int lb
, int l
, int n
) {
39 if (c
>= l
) return -1;
41 if (b
>= 0xC0) { /* 1100 0000 */
44 if (b
>= 0xC0 || b
< 0x80) break;
45 /* break unless b is 10------ */
52 if (c
<= lb
) return -1;
54 if (b
>= 0x80) { /* 1000 0000 */
57 if (b
>= 0xC0) break; /* 1100 0000 */
66 /* Code for character groupings: utf8 cases */
68 static int get_utf8(const symbol
* p
, int c
, int l
, int * slot
) {
72 if (b0
< 0xC0 || c
== l
) { /* 1100 0000 */
73 * slot
= b0
; return 1;
76 if (b0
< 0xE0 || c
== l
) { /* 1110 0000 */
77 * slot
= (b0
& 0x1F) << 6 | (b1
& 0x3F); return 2;
79 * slot
= (b0
& 0xF) << 12 | (b1
& 0x3F) << 6 | (*p
& 0x3F); return 3;
82 static int get_b_utf8(const symbol
* p
, int c
, int lb
, int * slot
) {
84 if (c
<= lb
) return 0;
86 if (b0
< 0x80 || c
== lb
) { /* 1000 0000 */
87 * slot
= b0
; return 1;
90 if (b1
>= 0xC0 || c
== lb
) { /* 1100 0000 */
91 * slot
= (b1
& 0x1F) << 6 | (b0
& 0x3F); return 2;
93 * slot
= (*p
& 0xF) << 12 | (b1
& 0x3F) << 6 | (b0
& 0x3F); return 3;
96 extern int in_grouping_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
98 int w
= get_utf8(z
->p
, z
->c
, z
->l
, & ch
);
100 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
104 extern int in_grouping_b_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
106 int w
= get_b_utf8(z
->p
, z
->c
, z
->lb
, & ch
);
108 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
112 extern int out_grouping_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
114 int w
= get_utf8(z
->p
, z
->c
, z
->l
, & ch
);
116 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
120 extern int out_grouping_b_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
122 int w
= get_b_utf8(z
->p
, z
->c
, z
->lb
, & ch
);
124 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
128 /* Code for character groupings: non-utf8 cases */
130 extern int in_grouping(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
132 if (z
->c
>= z
->l
) return 0;
134 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
138 extern int in_grouping_b(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
140 if (z
->c
<= z
->lb
) return 0;
142 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
146 extern int out_grouping(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
148 if (z
->c
>= z
->l
) return 0;
150 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
154 extern int out_grouping_b(struct SN_env
* z
, const unsigned char * s
, int min
, int max
) {
156 if (z
->c
<= z
->lb
) return 0;
158 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0) return 0;
162 extern int eq_s(struct SN_env
* z
, int s_size
, const symbol
* s
) {
163 if (z
->l
- z
->c
< s_size
|| memcmp(z
->p
+ z
->c
, s
, s_size
* sizeof(symbol
)) != 0) return 0;
164 z
->c
+= s_size
; return 1;
167 extern int eq_s_b(struct SN_env
* z
, int s_size
, const symbol
* s
) {
168 if (z
->c
- z
->lb
< s_size
|| memcmp(z
->p
+ z
->c
- s_size
, s
, s_size
* sizeof(symbol
)) != 0) return 0;
169 z
->c
-= s_size
; return 1;
172 extern int eq_v(struct SN_env
* z
, const symbol
* p
) {
173 return eq_s(z
, SIZE(p
), p
);
176 extern int eq_v_b(struct SN_env
* z
, const symbol
* p
) {
177 return eq_s_b(z
, SIZE(p
), p
);
180 extern int find_among(struct SN_env
* z
, const struct among
* v
, int v_size
) {
185 int c
= z
->c
; int l
= z
->l
;
186 symbol
* q
= z
->p
+ c
;
188 const struct among
* w
;
193 int first_key_inspected
= 0;
196 int k
= i
+ ((j
- i
) >> 1);
198 int common
= common_i
< common_j
? common_i
: common_j
; /* smaller */
201 int i
; for (i
= common
; i
< w
->s_size
; i
++) {
202 if (c
+ common
== l
) { diff
= -1; break; }
203 diff
= q
[common
] - w
->s
[i
];
204 if (diff
!= 0) break;
208 if (diff
< 0) { j
= k
; common_j
= common
; }
209 else { i
= k
; common_i
= common
; }
211 if (i
> 0) break; /* v->s has been inspected */
212 if (j
== i
) break; /* only one item in v */
214 /* - but now we need to go round once more to get
215 v->s inspected. This looks messy, but is actually
216 the optimal approach. */
218 if (first_key_inspected
) break;
219 first_key_inspected
= 1;
224 if (common_i
>= w
->s_size
) {
225 z
->c
= c
+ w
->s_size
;
226 if (w
->function
== 0) return w
->result
;
228 int res
= w
->function(z
);
229 z
->c
= c
+ w
->s_size
;
230 if (res
) return w
->result
;
238 /* find_among_b is for backwards processing. Same comments apply */
240 extern int find_among_b(struct SN_env
* z
, const struct among
* v
, int v_size
) {
245 int c
= z
->c
; int lb
= z
->lb
;
246 symbol
* q
= z
->p
+ c
- 1;
248 const struct among
* w
;
253 int first_key_inspected
= 0;
256 int k
= i
+ ((j
- i
) >> 1);
258 int common
= common_i
< common_j
? common_i
: common_j
;
261 int i
; for (i
= w
->s_size
- 1 - common
; i
>= 0; i
--) {
262 if (c
- common
== lb
) { diff
= -1; break; }
263 diff
= q
[- common
] - w
->s
[i
];
264 if (diff
!= 0) break;
268 if (diff
< 0) { j
= k
; common_j
= common
; }
269 else { i
= k
; common_i
= common
; }
273 if (first_key_inspected
) break;
274 first_key_inspected
= 1;
279 if (common_i
>= w
->s_size
) {
280 z
->c
= c
- w
->s_size
;
281 if (w
->function
== 0) return w
->result
;
283 int res
= w
->function(z
);
284 z
->c
= c
- w
->s_size
;
285 if (res
) return w
->result
;
294 /* Increase the size of the buffer pointed to by p to at least n symbols.
295 * If insufficient memory, returns NULL and frees the old buffer.
297 static symbol
* increase_size(symbol
* p
, int n
) {
299 int new_size
= n
+ 20;
300 void * mem
= realloc((char *) p
- HEAD
,
301 HEAD
+ (new_size
+ 1) * sizeof(symbol
));
306 q
= (symbol
*) (HEAD
+ (char *)mem
);
307 CAPACITY(q
) = new_size
;
311 /* to replace symbols between c_bra and c_ket in z->p by the
313 Returns 0 on success, -1 on error.
314 Also, frees z->p (and sets it to NULL) on error.
316 extern int replace_s(struct SN_env
* z
, int c_bra
, int c_ket
, int s_size
, const symbol
* s
, int * adjptr
)
322 if (z
->p
== NULL
) return -1;
324 adjustment
= s_size
- (c_ket
- c_bra
);
326 if (adjustment
!= 0) {
327 if (adjustment
+ len
> CAPACITY(z
->p
)) {
328 z
->p
= increase_size(z
->p
, adjustment
+ len
);
329 if (z
->p
== NULL
) return -1;
331 memmove(z
->p
+ c_ket
+ adjustment
,
333 (len
- c_ket
) * sizeof(symbol
));
334 SET_SIZE(z
->p
, adjustment
+ len
);
342 unless (s_size
== 0) memmove(z
->p
+ c_bra
, s
, s_size
* sizeof(symbol
));
344 *adjptr
= adjustment
;
348 static int slice_check(struct SN_env
* z
) {
354 z
->l
> SIZE(z
->p
)) /* this line could be removed */
357 fprintf(stderr
, "faulty slice operation:\n");
365 extern int slice_from_s(struct SN_env
* z
, int s_size
, const symbol
* s
) {
366 if (slice_check(z
)) return -1;
367 return replace_s(z
, z
->bra
, z
->ket
, s_size
, s
, NULL
);
370 extern int slice_from_v(struct SN_env
* z
, const symbol
* p
) {
371 return slice_from_s(z
, SIZE(p
), p
);
374 extern int slice_del(struct SN_env
* z
) {
375 return slice_from_s(z
, 0, 0);
378 extern int insert_s(struct SN_env
* z
, int bra
, int ket
, int s_size
, const symbol
* s
) {
380 if (replace_s(z
, bra
, ket
, s_size
, s
, &adjustment
))
382 if (bra
<= z
->bra
) z
->bra
+= adjustment
;
383 if (bra
<= z
->ket
) z
->ket
+= adjustment
;
387 extern int insert_v(struct SN_env
* z
, int bra
, int ket
, const symbol
* p
) {
389 if (replace_s(z
, bra
, ket
, SIZE(p
), p
, &adjustment
))
391 if (bra
<= z
->bra
) z
->bra
+= adjustment
;
392 if (bra
<= z
->ket
) z
->ket
+= adjustment
;
396 extern symbol
* slice_to(struct SN_env
* z
, symbol
* p
) {
397 if (slice_check(z
)) {
402 int len
= z
->ket
- z
->bra
;
403 if (CAPACITY(p
) < len
) {
404 p
= increase_size(p
, len
);
408 memmove(p
, z
->p
+ z
->bra
, len
* sizeof(symbol
));
414 extern symbol
* assign_to(struct SN_env
* z
, symbol
* p
) {
416 if (CAPACITY(p
) < len
) {
417 p
= increase_size(p
, len
);
421 memmove(p
, z
->p
, len
* sizeof(symbol
));
427 extern void debug(struct SN_env
* z
, int number
, int line_count
) {
429 int limit
= SIZE(z
->p
);
430 /*if (number >= 0) printf("%3d (line %4d): '", number, line_count);*/
431 if (number
>= 0) printf("%3d (line %4d): [%d]'", number
, line_count
,limit
);
432 for (i
= 0; i
<= limit
; i
++) {
433 if (z
->lb
== i
) printf("{");
434 if (z
->bra
== i
) printf("[");
435 if (z
->c
== i
) printf("|");
436 if (z
->ket
== i
) printf("]");
437 if (z
->l
== i
) printf("}");
440 if (ch
== 0) ch
= '#';