3 #define unless(C) if(!(C))
7 extern symbol
* create_s(void) {
9 void * mem
= malloc(HEAD
+ (CREATE_SIZE
+ 1) * sizeof(symbol
));
10 if (mem
== NULL
) return NULL
;
11 p
= (symbol
*) (HEAD
+ (char *) mem
);
12 CAPACITY(p
) = CREATE_SIZE
;
13 SET_SIZE(p
, CREATE_SIZE
);
17 extern void lose_s(symbol
* p
) {
18 if (p
== NULL
) return;
19 free((char *) p
- HEAD
);
23 new_p = skip_utf8(p, c, lb, l, n); skips n characters forwards from p + c
24 if n +ve, or n characters backwards from p + c - 1 if n -ve. new_p is the new
25 position, or 0 on failure.
27 -- used to implement hop and next in the utf8 case.
30 extern int skip_utf8(const symbol
* p
, int c
, int lb
, int l
, int n
) {
34 if (c
>= l
) return -1;
36 if (b
>= 0xC0) { /* 1100 0000 */
39 if (b
>= 0xC0 || b
< 0x80) break;
40 /* break unless b is 10------ */
47 if (c
<= lb
) return -1;
49 if (b
>= 0x80) { /* 1000 0000 */
52 if (b
>= 0xC0) break; /* 1100 0000 */
61 /* Code for character groupings: utf8 cases */
63 static int get_utf8(const symbol
* p
, int c
, int l
, int * slot
) {
67 if (b0
< 0xC0 || c
== l
) { /* 1100 0000 */
68 * slot
= b0
; return 1;
71 if (b0
< 0xE0 || c
== l
) { /* 1110 0000 */
72 * slot
= (b0
& 0x1F) << 6 | (b1
& 0x3F); return 2;
74 * slot
= (b0
& 0xF) << 12 | (b1
& 0x3F) << 6 | (p
[c
] & 0x3F); return 3;
77 static int get_b_utf8(const symbol
* p
, int c
, int lb
, int * slot
) {
79 if (c
<= lb
) return 0;
81 if (b0
< 0x80 || c
== lb
) { /* 1000 0000 */
82 * slot
= b0
; return 1;
85 if (b1
>= 0xC0 || c
== lb
) { /* 1100 0000 */
86 * slot
= (b1
& 0x1F) << 6 | (b0
& 0x3F); return 2;
88 * slot
= (p
[c
] & 0xF) << 12 | (b1
& 0x3F) << 6 | (b0
& 0x3F); return 3;
91 extern int in_grouping_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
94 int w
= get_utf8(z
->p
, z
->c
, z
->l
, & ch
);
96 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
103 extern int in_grouping_b_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
106 int w
= get_b_utf8(z
->p
, z
->c
, z
->lb
, & ch
);
107 unless (w
) return -1;
108 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
115 extern int out_grouping_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
118 int w
= get_utf8(z
->p
, z
->c
, z
->l
, & ch
);
119 unless (w
) return -1;
120 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
127 extern int out_grouping_b_U(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
130 int w
= get_b_utf8(z
->p
, z
->c
, z
->lb
, & ch
);
131 unless (w
) return -1;
132 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
139 /* Code for character groupings: non-utf8 cases */
141 extern int in_grouping(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
144 if (z
->c
>= z
->l
) return -1;
146 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
153 extern int in_grouping_b(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
156 if (z
->c
<= z
->lb
) return -1;
158 if (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
165 extern int out_grouping(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
168 if (z
->c
>= z
->l
) return -1;
170 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
177 extern int out_grouping_b(struct SN_env
* z
, const unsigned char * s
, int min
, int max
, int repeat
) {
180 if (z
->c
<= z
->lb
) return -1;
182 unless (ch
> max
|| (ch
-= min
) < 0 || (s
[ch
>> 3] & (0X1 << (ch
& 0X7))) == 0)
189 extern int eq_s(struct SN_env
* z
, int s_size
, const symbol
* s
) {
190 if (z
->l
- z
->c
< s_size
|| memcmp(z
->p
+ z
->c
, s
, s_size
* sizeof(symbol
)) != 0) return 0;
191 z
->c
+= s_size
; return 1;
194 extern int eq_s_b(struct SN_env
* z
, int s_size
, const symbol
* s
) {
195 if (z
->c
- z
->lb
< s_size
|| memcmp(z
->p
+ z
->c
- s_size
, s
, s_size
* sizeof(symbol
)) != 0) return 0;
196 z
->c
-= s_size
; return 1;
199 extern int eq_v(struct SN_env
* z
, const symbol
* p
) {
200 return eq_s(z
, SIZE(p
), p
);
203 extern int eq_v_b(struct SN_env
* z
, const symbol
* p
) {
204 return eq_s_b(z
, SIZE(p
), p
);
207 extern int find_among(struct SN_env
* z
, const struct among
* v
, int v_size
) {
212 int c
= z
->c
; int l
= z
->l
;
213 symbol
* q
= z
->p
+ c
;
215 const struct among
* w
;
220 int first_key_inspected
= 0;
223 int k
= i
+ ((j
- i
) >> 1);
225 int common
= common_i
< common_j
? common_i
: common_j
; /* smaller */
228 int i2
; for (i2
= common
; i2
< w
->s_size
; i2
++) {
229 if (c
+ common
== l
) { diff
= -1; break; }
230 diff
= q
[common
] - w
->s
[i2
];
231 if (diff
!= 0) break;
235 if (diff
< 0) { j
= k
; common_j
= common
; }
236 else { i
= k
; common_i
= common
; }
238 if (i
> 0) break; /* v->s has been inspected */
239 if (j
== i
) break; /* only one item in v */
241 /* - but now we need to go round once more to get
242 v->s inspected. This looks messy, but is actually
243 the optimal approach. */
245 if (first_key_inspected
) break;
246 first_key_inspected
= 1;
251 if (common_i
>= w
->s_size
) {
252 z
->c
= c
+ w
->s_size
;
253 if (w
->function
== 0) return w
->result
;
255 int res
= w
->function(z
);
256 z
->c
= c
+ w
->s_size
;
257 if (res
) return w
->result
;
265 /* find_among_b is for backwards processing. Same comments apply */
267 extern int find_among_b(struct SN_env
* z
, const struct among
* v
, int v_size
) {
272 int c
= z
->c
; int lb
= z
->lb
;
273 symbol
* q
= z
->p
+ c
- 1;
275 const struct among
* w
;
280 int first_key_inspected
= 0;
283 int k
= i
+ ((j
- i
) >> 1);
285 int common
= common_i
< common_j
? common_i
: common_j
;
288 int i2
; for (i2
= w
->s_size
- 1 - common
; i2
>= 0; i2
--) {
289 if (c
- common
== lb
) { diff
= -1; break; }
290 diff
= q
[- common
] - w
->s
[i2
];
291 if (diff
!= 0) break;
295 if (diff
< 0) { j
= k
; common_j
= common
; }
296 else { i
= k
; common_i
= common
; }
300 if (first_key_inspected
) break;
301 first_key_inspected
= 1;
306 if (common_i
>= w
->s_size
) {
307 z
->c
= c
- w
->s_size
;
308 if (w
->function
== 0) return w
->result
;
310 int res
= w
->function(z
);
311 z
->c
= c
- w
->s_size
;
312 if (res
) return w
->result
;
321 /* Increase the size of the buffer pointed to by p to at least n symbols.
322 * If insufficient memory, returns NULL and frees the old buffer.
324 static symbol
* increase_size(symbol
* p
, int n
) {
326 int new_size
= n
+ 20;
327 void * mem
= realloc((char *) p
- HEAD
,
328 HEAD
+ (new_size
+ 1) * sizeof(symbol
));
333 q
= (symbol
*) (HEAD
+ (char *)mem
);
334 CAPACITY(q
) = new_size
;
338 /* to replace symbols between c_bra and c_ket in z->p by the
340 Returns 0 on success, -1 on error.
341 Also, frees z->p (and sets it to NULL) on error.
343 extern int replace_s(struct SN_env
* z
, int c_bra
, int c_ket
, int s_size
, const symbol
* s
, int * adjptr
)
349 if (z
->p
== NULL
) return -1;
351 adjustment
= s_size
- (c_ket
- c_bra
);
353 if (adjustment
!= 0) {
354 if (adjustment
+ len
> CAPACITY(z
->p
)) {
355 z
->p
= increase_size(z
->p
, adjustment
+ len
);
356 if (z
->p
== NULL
) return -1;
358 memmove(z
->p
+ c_ket
+ adjustment
,
360 (len
- c_ket
) * sizeof(symbol
));
361 SET_SIZE(z
->p
, adjustment
+ len
);
369 unless (s_size
== 0) memmove(z
->p
+ c_bra
, s
, s_size
* sizeof(symbol
));
371 *adjptr
= adjustment
;
375 static int slice_check(struct SN_env
* z
) {
381 z
->l
> SIZE(z
->p
)) /* this line could be removed */
384 fprintf(stderr
, "faulty slice operation:\n");
392 extern int slice_from_s(struct SN_env
* z
, int s_size
, const symbol
* s
) {
393 if (slice_check(z
)) return -1;
394 return replace_s(z
, z
->bra
, z
->ket
, s_size
, s
, NULL
);
397 extern int slice_from_v(struct SN_env
* z
, const symbol
* p
) {
398 return slice_from_s(z
, SIZE(p
), p
);
401 extern int slice_del(struct SN_env
* z
) {
402 return slice_from_s(z
, 0, 0);
405 extern int insert_s(struct SN_env
* z
, int bra
, int ket
, int s_size
, const symbol
* s
) {
407 if (replace_s(z
, bra
, ket
, s_size
, s
, &adjustment
))
409 if (bra
<= z
->bra
) z
->bra
+= adjustment
;
410 if (bra
<= z
->ket
) z
->ket
+= adjustment
;
414 extern int insert_v(struct SN_env
* z
, int bra
, int ket
, const symbol
* p
) {
416 if (replace_s(z
, bra
, ket
, SIZE(p
), p
, &adjustment
))
418 if (bra
<= z
->bra
) z
->bra
+= adjustment
;
419 if (bra
<= z
->ket
) z
->ket
+= adjustment
;
423 extern symbol
* slice_to(struct SN_env
* z
, symbol
* p
) {
424 if (slice_check(z
)) {
429 int len
= z
->ket
- z
->bra
;
430 if (CAPACITY(p
) < len
) {
431 p
= increase_size(p
, len
);
435 memmove(p
, z
->p
+ z
->bra
, len
* sizeof(symbol
));
441 extern symbol
* assign_to(struct SN_env
* z
, symbol
* p
) {
443 if (CAPACITY(p
) < len
) {
444 p
= increase_size(p
, len
);
448 memmove(p
, z
->p
, len
* sizeof(symbol
));
454 extern void debug(struct SN_env
* z
, int number
, int line_count
) {
456 int limit
= SIZE(z
->p
);
457 /*if (number >= 0) printf("%3d (line %4d): '", number, line_count);*/
458 if (number
>= 0) printf("%3d (line %4d): [%d]'", number
, line_count
,limit
);
459 for (i
= 0; i
<= limit
; i
++) {
460 if (z
->lb
== i
) printf("{");
461 if (z
->bra
== i
) printf("[");
462 if (z
->c
== i
) printf("|");
463 if (z
->ket
== i
) printf("]");
464 if (z
->l
== i
) printf("}");
467 if (ch
== 0) ch
= '#';