~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjlib-util/src/pjlib-util/scanner.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: scanner.c 4209 2012-07-18 10:21:00Z ming $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pjlib-util/scanner.h>
 
21
#include <pj/ctype.h>
 
22
#include <pj/string.h>
 
23
#include <pj/except.h>
 
24
#include <pj/os.h>
 
25
#include <pj/errno.h>
 
26
#include <pj/assert.h>
 
27
 
 
28
#define PJ_SCAN_IS_SPACE(c)             ((c)==' ' || (c)=='\t')
 
29
#define PJ_SCAN_IS_NEWLINE(c)           ((c)=='\r' || (c)=='\n')
 
30
#define PJ_SCAN_IS_PROBABLY_SPACE(c)    ((c) <= 32)
 
31
#define PJ_SCAN_CHECK_EOF(s)            (s != scanner->end)
 
32
 
 
33
 
 
34
#if defined(PJ_SCANNER_USE_BITWISE) && PJ_SCANNER_USE_BITWISE != 0
 
35
#  include "scanner_cis_bitwise.c"
 
36
#else
 
37
#  include "scanner_cis_uint.c"
 
38
#endif
 
39
 
 
40
 
 
41
static void pj_scan_syntax_err(pj_scanner *scanner)
 
42
{
 
43
    (*scanner->callback)(scanner);
 
44
}
 
45
 
 
46
 
 
47
PJ_DEF(void) pj_cis_add_range(pj_cis_t *cis, int cstart, int cend)
 
48
{
 
49
    /* Can not set zero. This is the requirement of the parser. */
 
50
    pj_assert(cstart > 0);
 
51
 
 
52
    while (cstart != cend) {
 
53
        PJ_CIS_SET(cis, cstart);
 
54
        ++cstart;
 
55
    }
 
56
}
 
57
 
 
58
PJ_DEF(void) pj_cis_add_alpha(pj_cis_t *cis)
 
59
{
 
60
    pj_cis_add_range( cis, 'a', 'z'+1);
 
61
    pj_cis_add_range( cis, 'A', 'Z'+1);
 
62
}
 
63
 
 
64
PJ_DEF(void) pj_cis_add_num(pj_cis_t *cis)
 
65
{
 
66
    pj_cis_add_range( cis, '0', '9'+1);
 
67
}
 
68
 
 
69
PJ_DEF(void) pj_cis_add_str( pj_cis_t *cis, const char *str)
 
70
{
 
71
    while (*str) {
 
72
        PJ_CIS_SET(cis, *str);
 
73
        ++str;
 
74
    }
 
75
}
 
76
 
 
77
PJ_DEF(void) pj_cis_add_cis( pj_cis_t *cis, const pj_cis_t *rhs)
 
78
{
 
79
    int i;
 
80
    for (i=0; i<256; ++i) {
 
81
        if (PJ_CIS_ISSET(rhs, i))
 
82
            PJ_CIS_SET(cis, i);
 
83
    }
 
84
}
 
85
 
 
86
PJ_DEF(void) pj_cis_del_range( pj_cis_t *cis, int cstart, int cend)
 
87
{
 
88
    while (cstart != cend) {
 
89
        PJ_CIS_CLR(cis, cstart);
 
90
        cstart++;
 
91
    }
 
92
}
 
93
 
 
94
PJ_DEF(void) pj_cis_del_str( pj_cis_t *cis, const char *str)
 
95
{
 
96
    while (*str) {
 
97
        PJ_CIS_CLR(cis, *str);
 
98
        ++str;
 
99
    }
 
100
}
 
101
 
 
102
PJ_DEF(void) pj_cis_invert( pj_cis_t *cis )
 
103
{
 
104
    unsigned i;
 
105
    /* Can not set zero. This is the requirement of the parser. */
 
106
    for (i=1; i<256; ++i) {
 
107
        if (PJ_CIS_ISSET(cis,i))
 
108
            PJ_CIS_CLR(cis,i);
 
109
        else
 
110
            PJ_CIS_SET(cis,i);
 
111
    }
 
112
}
 
113
 
 
114
PJ_DEF(void) pj_scan_init( pj_scanner *scanner, char *bufstart, int buflen, 
 
115
                           unsigned options, pj_syn_err_func_ptr callback )
 
116
{
 
117
    PJ_CHECK_STACK();
 
118
 
 
119
    scanner->begin = scanner->curptr = bufstart;
 
120
    scanner->end = bufstart + buflen;
 
121
    scanner->line = 1;
 
122
    scanner->start_line = scanner->begin;
 
123
    scanner->callback = callback;
 
124
    scanner->skip_ws = options;
 
125
 
 
126
    if (scanner->skip_ws) 
 
127
        pj_scan_skip_whitespace(scanner);
 
128
}
 
129
 
 
130
 
 
131
PJ_DEF(void) pj_scan_fini( pj_scanner *scanner )
 
132
{
 
133
    PJ_CHECK_STACK();
 
134
    PJ_UNUSED_ARG(scanner);
 
135
}
 
136
 
 
137
PJ_DEF(void) pj_scan_skip_whitespace( pj_scanner *scanner )
 
138
{
 
139
    register char *s = scanner->curptr;
 
140
 
 
141
    while (PJ_SCAN_IS_SPACE(*s)) {
 
142
        ++s;
 
143
    }
 
144
 
 
145
    if (PJ_SCAN_IS_NEWLINE(*s) && (scanner->skip_ws & PJ_SCAN_AUTOSKIP_NEWLINE)) {
 
146
        for (;;) {
 
147
            if (*s == '\r') {
 
148
                ++s;
 
149
                if (*s == '\n') ++s;
 
150
                ++scanner->line;
 
151
                scanner->curptr = scanner->start_line = s;
 
152
            } else if (*s == '\n') {
 
153
                ++s;
 
154
                ++scanner->line;
 
155
                scanner->curptr = scanner->start_line = s;
 
156
            } else if (PJ_SCAN_IS_SPACE(*s)) {
 
157
                do {
 
158
                    ++s;
 
159
                } while (PJ_SCAN_IS_SPACE(*s));
 
160
            } else {
 
161
                break;
 
162
            }
 
163
        }
 
164
    }
 
165
 
 
166
    if (PJ_SCAN_IS_NEWLINE(*s) && (scanner->skip_ws & PJ_SCAN_AUTOSKIP_WS_HEADER)==PJ_SCAN_AUTOSKIP_WS_HEADER) {
 
167
        /* Check for header continuation. */
 
168
        scanner->curptr = s;
 
169
 
 
170
        if (*s == '\r') {
 
171
            ++s;
 
172
        }
 
173
        if (*s == '\n') {
 
174
            ++s;
 
175
        }
 
176
        scanner->start_line = s;
 
177
 
 
178
        if (PJ_SCAN_IS_SPACE(*s)) {
 
179
            register char *t = s;
 
180
            do {
 
181
                ++t;
 
182
            } while (PJ_SCAN_IS_SPACE(*t));
 
183
 
 
184
            ++scanner->line;
 
185
            scanner->curptr = t;
 
186
        }
 
187
    } else {
 
188
        scanner->curptr = s;
 
189
    }
 
190
}
 
191
 
 
192
PJ_DEF(void) pj_scan_skip_line( pj_scanner *scanner )
 
193
{
 
194
    char *s = pj_ansi_strchr(scanner->curptr, '\n');
 
195
    if (!s) {
 
196
        scanner->curptr = scanner->end;
 
197
    } else {
 
198
        scanner->curptr = scanner->start_line = s+1;
 
199
        scanner->line++;
 
200
   }
 
201
}
 
202
 
 
203
PJ_DEF(int) pj_scan_peek( pj_scanner *scanner,
 
204
                          const pj_cis_t *spec, pj_str_t *out)
 
205
{
 
206
    register char *s = scanner->curptr;
 
207
 
 
208
    if (s >= scanner->end) {
 
209
        pj_scan_syntax_err(scanner);
 
210
        return -1;
 
211
    }
 
212
 
 
213
    /* Don't need to check EOF with PJ_SCAN_CHECK_EOF(s) */
 
214
    while (pj_cis_match(spec, *s))
 
215
        ++s;
 
216
 
 
217
    pj_strset3(out, scanner->curptr, s);
 
218
    return *s;
 
219
}
 
220
 
 
221
 
 
222
PJ_DEF(int) pj_scan_peek_n( pj_scanner *scanner,
 
223
                             pj_size_t len, pj_str_t *out)
 
224
{
 
225
    char *endpos = scanner->curptr + len;
 
226
 
 
227
    if (endpos > scanner->end) {
 
228
        pj_scan_syntax_err(scanner);
 
229
        return -1;
 
230
    }
 
231
 
 
232
    pj_strset(out, scanner->curptr, len);
 
233
    return *endpos;
 
234
}
 
235
 
 
236
 
 
237
PJ_DEF(int) pj_scan_peek_until( pj_scanner *scanner,
 
238
                                const pj_cis_t *spec, 
 
239
                                pj_str_t *out)
 
240
{
 
241
    register char *s = scanner->curptr;
 
242
 
 
243
    if (s >= scanner->end) {
 
244
        pj_scan_syntax_err(scanner);
 
245
        return -1;
 
246
    }
 
247
 
 
248
    while (PJ_SCAN_CHECK_EOF(s) && !pj_cis_match( spec, *s))
 
249
        ++s;
 
250
 
 
251
    pj_strset3(out, scanner->curptr, s);
 
252
    return *s;
 
253
}
 
254
 
 
255
 
 
256
PJ_DEF(void) pj_scan_get( pj_scanner *scanner,
 
257
                          const pj_cis_t *spec, pj_str_t *out)
 
258
{
 
259
    register char *s = scanner->curptr;
 
260
 
 
261
    pj_assert(pj_cis_match(spec,0)==0);
 
262
 
 
263
    /* EOF is detected implicitly */
 
264
    if (!pj_cis_match(spec, *s)) {
 
265
        pj_scan_syntax_err(scanner);
 
266
        return;
 
267
    }
 
268
 
 
269
    do {
 
270
        ++s;
 
271
    } while (pj_cis_match(spec, *s));
 
272
    /* No need to check EOF here (PJ_SCAN_CHECK_EOF(s)) because
 
273
     * buffer is NULL terminated and pj_cis_match(spec,0) should be
 
274
     * false.
 
275
     */
 
276
 
 
277
    pj_strset3(out, scanner->curptr, s);
 
278
 
 
279
    scanner->curptr = s;
 
280
 
 
281
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 
282
        pj_scan_skip_whitespace(scanner);    
 
283
    }
 
284
}
 
285
 
 
286
 
 
287
PJ_DEF(void) pj_scan_get_unescape( pj_scanner *scanner,
 
288
                                   const pj_cis_t *spec, pj_str_t *out)
 
289
{
 
290
    register char *s = scanner->curptr;
 
291
    char *dst = s;
 
292
 
 
293
    pj_assert(pj_cis_match(spec,0)==0);
 
294
 
 
295
    /* Must not match character '%' */
 
296
    pj_assert(pj_cis_match(spec,'%')==0);
 
297
 
 
298
    /* EOF is detected implicitly */
 
299
    if (!pj_cis_match(spec, *s) && *s != '%') {
 
300
        pj_scan_syntax_err(scanner);
 
301
        return;
 
302
    }
 
303
 
 
304
    out->ptr = s;
 
305
    do {
 
306
        if (*s == '%') {
 
307
            if (s+3 <= scanner->end && pj_isxdigit(*(s+1)) && 
 
308
                pj_isxdigit(*(s+2))) 
 
309
            {
 
310
                *dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(s+1)) << 4) +
 
311
                                      pj_hex_digit_to_val(*(s+2)));
 
312
                ++dst;
 
313
                s += 3;
 
314
            } else {
 
315
                *dst++ = *s++;
 
316
                *dst++ = *s++;
 
317
                break;
 
318
            }
 
319
        }
 
320
        
 
321
        if (pj_cis_match(spec, *s)) {
 
322
            char *start = s;
 
323
            do {
 
324
                ++s;
 
325
            } while (pj_cis_match(spec, *s));
 
326
 
 
327
            if (dst != start) pj_memmove(dst, start, s-start);
 
328
            dst += (s-start);
 
329
        } 
 
330
        
 
331
    } while (*s == '%');
 
332
 
 
333
    scanner->curptr = s;
 
334
    out->slen = (dst - out->ptr);
 
335
 
 
336
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 
337
        pj_scan_skip_whitespace(scanner);    
 
338
    }
 
339
}
 
340
 
 
341
 
 
342
PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner,
 
343
                                int begin_quote, int end_quote, 
 
344
                                pj_str_t *out)
 
345
{
 
346
    char beg = (char)begin_quote;
 
347
    char end = (char)end_quote;
 
348
    pj_scan_get_quotes(scanner, &beg, &end, 1, out);
 
349
}
 
350
 
 
351
PJ_DEF(void) pj_scan_get_quotes(pj_scanner *scanner,
 
352
                                const char *begin_quote, const char *end_quote,
 
353
                                int qsize, pj_str_t *out)
 
354
{
 
355
    register char *s = scanner->curptr;
 
356
    int qpair = -1;
 
357
    int i;
 
358
 
 
359
    pj_assert(qsize > 0);
 
360
 
 
361
    /* Check and eat the begin_quote. */
 
362
    for (i = 0; i < qsize; ++i) {
 
363
        if (*s == begin_quote[i]) {
 
364
            qpair = i;
 
365
            break;
 
366
        }
 
367
    }
 
368
    if (qpair == -1) {
 
369
        pj_scan_syntax_err(scanner);
 
370
        return;
 
371
    }
 
372
    ++s;
 
373
 
 
374
    /* Loop until end_quote is found. 
 
375
     */
 
376
    do {
 
377
        /* loop until end_quote is found. */
 
378
        while (PJ_SCAN_CHECK_EOF(s) && *s != '\n' && *s != end_quote[qpair]) {
 
379
            ++s;
 
380
        }
 
381
 
 
382
        /* check that no backslash character precedes the end_quote. */
 
383
        if (*s == end_quote[qpair]) {
 
384
            if (*(s-1) == '\\') {
 
385
                if (s-2 == scanner->begin) {
 
386
                    break;
 
387
                } else {
 
388
                    char *q = s-2;
 
389
                    char *r = s-2;
 
390
 
 
391
                    while (r != scanner->begin && *r == '\\') {
 
392
                        --r;
 
393
                    }
 
394
                    /* break from main loop if we have odd number of backslashes */
 
395
                    if (((unsigned)(q-r) & 0x01) == 1) {
 
396
                        break;
 
397
                    }
 
398
                    ++s;
 
399
                }
 
400
            } else {
 
401
                /* end_quote is not preceeded by backslash. break now. */
 
402
                break;
 
403
            }
 
404
        } else {
 
405
            /* loop ended by non-end_quote character. break now. */
 
406
            break;
 
407
        }
 
408
    } while (1);
 
409
 
 
410
    /* Check and eat the end quote. */
 
411
    if (*s != end_quote[qpair]) {
 
412
        pj_scan_syntax_err(scanner);
 
413
        return;
 
414
    }
 
415
    ++s;
 
416
 
 
417
    pj_strset3(out, scanner->curptr, s);
 
418
 
 
419
    scanner->curptr = s;
 
420
 
 
421
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 
422
        pj_scan_skip_whitespace(scanner);
 
423
    }
 
424
}
 
425
 
 
426
 
 
427
PJ_DEF(void) pj_scan_get_n( pj_scanner *scanner,
 
428
                            unsigned N, pj_str_t *out)
 
429
{
 
430
    if (scanner->curptr + N > scanner->end) {
 
431
        pj_scan_syntax_err(scanner);
 
432
        return;
 
433
    }
 
434
 
 
435
    pj_strset(out, scanner->curptr, N);
 
436
    
 
437
    scanner->curptr += N;
 
438
 
 
439
    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
 
440
        pj_scan_skip_whitespace(scanner);
 
441
    }
 
442
}
 
443
 
 
444
 
 
445
PJ_DEF(int) pj_scan_get_char( pj_scanner *scanner )
 
446
{
 
447
    int chr = *scanner->curptr;
 
448
 
 
449
    if (!chr) {
 
450
        pj_scan_syntax_err(scanner);
 
451
        return 0;
 
452
    }
 
453
 
 
454
    ++scanner->curptr;
 
455
 
 
456
    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
 
457
        pj_scan_skip_whitespace(scanner);
 
458
    }
 
459
    return chr;
 
460
}
 
461
 
 
462
 
 
463
PJ_DEF(void) pj_scan_get_newline( pj_scanner *scanner )
 
464
{
 
465
    if (!PJ_SCAN_IS_NEWLINE(*scanner->curptr)) {
 
466
        pj_scan_syntax_err(scanner);
 
467
        return;
 
468
    }
 
469
 
 
470
    if (*scanner->curptr == '\r') {
 
471
        ++scanner->curptr;
 
472
    }
 
473
    if (*scanner->curptr == '\n') {
 
474
        ++scanner->curptr;
 
475
    }
 
476
 
 
477
    ++scanner->line;
 
478
    scanner->start_line = scanner->curptr;
 
479
 
 
480
    /**
 
481
     * This probably is a bug, see PROTOS test #2480.
 
482
     * This would cause scanner to incorrectly eat two new lines, e.g.
 
483
     * when parsing:
 
484
     *   
 
485
     *  Content-Length: 120\r\n
 
486
     *  \r\n
 
487
     *  <space><space><space>...
 
488
     *
 
489
     * When pj_scan_get_newline() is called to parse the first newline
 
490
     * in the Content-Length header, it will eat the second newline
 
491
     * too because it thinks that it's a header continuation.
 
492
     *
 
493
     * if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
 
494
     *    pj_scan_skip_whitespace(scanner);
 
495
     * }
 
496
     */
 
497
}
 
498
 
 
499
 
 
500
PJ_DEF(void) pj_scan_get_until( pj_scanner *scanner,
 
501
                                const pj_cis_t *spec, pj_str_t *out)
 
502
{
 
503
    register char *s = scanner->curptr;
 
504
 
 
505
    if (s >= scanner->end) {
 
506
        pj_scan_syntax_err(scanner);
 
507
        return;
 
508
    }
 
509
 
 
510
    while (PJ_SCAN_CHECK_EOF(s) && !pj_cis_match(spec, *s)) {
 
511
        ++s;
 
512
    }
 
513
 
 
514
    pj_strset3(out, scanner->curptr, s);
 
515
 
 
516
    scanner->curptr = s;
 
517
 
 
518
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 
519
        pj_scan_skip_whitespace(scanner);
 
520
    }
 
521
}
 
522
 
 
523
 
 
524
PJ_DEF(void) pj_scan_get_until_ch( pj_scanner *scanner, 
 
525
                                   int until_char, pj_str_t *out)
 
526
{
 
527
    register char *s = scanner->curptr;
 
528
 
 
529
    if (s >= scanner->end) {
 
530
        pj_scan_syntax_err(scanner);
 
531
        return;
 
532
    }
 
533
 
 
534
    while (PJ_SCAN_CHECK_EOF(s) && *s != until_char) {
 
535
        ++s;
 
536
    }
 
537
 
 
538
    pj_strset3(out, scanner->curptr, s);
 
539
 
 
540
    scanner->curptr = s;
 
541
 
 
542
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 
543
        pj_scan_skip_whitespace(scanner);
 
544
    }
 
545
}
 
546
 
 
547
 
 
548
PJ_DEF(void) pj_scan_get_until_chr( pj_scanner *scanner,
 
549
                                     const char *until_spec, pj_str_t *out)
 
550
{
 
551
    register char *s = scanner->curptr;
 
552
    int speclen;
 
553
 
 
554
    if (s >= scanner->end) {
 
555
        pj_scan_syntax_err(scanner);
 
556
        return;
 
557
    }
 
558
 
 
559
    speclen = strlen(until_spec);
 
560
    while (PJ_SCAN_CHECK_EOF(s) && !memchr(until_spec, *s, speclen)) {
 
561
        ++s;
 
562
    }
 
563
 
 
564
    pj_strset3(out, scanner->curptr, s);
 
565
 
 
566
    scanner->curptr = s;
 
567
 
 
568
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 
569
        pj_scan_skip_whitespace(scanner);
 
570
    }
 
571
}
 
572
 
 
573
PJ_DEF(void) pj_scan_advance_n( pj_scanner *scanner,
 
574
                                 unsigned N, pj_bool_t skip_ws)
 
575
{
 
576
    if (scanner->curptr + N > scanner->end) {
 
577
        pj_scan_syntax_err(scanner);
 
578
        return;
 
579
    }
 
580
 
 
581
    scanner->curptr += N;
 
582
 
 
583
    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws) {
 
584
        pj_scan_skip_whitespace(scanner);
 
585
    }
 
586
}
 
587
 
 
588
 
 
589
PJ_DEF(int) pj_scan_strcmp( pj_scanner *scanner, const char *s, int len)
 
590
{
 
591
    if (scanner->curptr + len > scanner->end) {
 
592
        pj_scan_syntax_err(scanner);
 
593
        return -1;
 
594
    }
 
595
    return strncmp(scanner->curptr, s, len);
 
596
}
 
597
 
 
598
 
 
599
PJ_DEF(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len)
 
600
{
 
601
    if (scanner->curptr + len > scanner->end) {
 
602
        pj_scan_syntax_err(scanner);
 
603
        return -1;
 
604
    }
 
605
    return pj_ansi_strnicmp(scanner->curptr, s, len);
 
606
}
 
607
 
 
608
PJ_DEF(int) pj_scan_stricmp_alnum( pj_scanner *scanner, const char *s, 
 
609
                                   int len)
 
610
{
 
611
    if (scanner->curptr + len > scanner->end) {
 
612
        pj_scan_syntax_err(scanner);
 
613
        return -1;
 
614
    }
 
615
    return strnicmp_alnum(scanner->curptr, s, len);
 
616
}
 
617
 
 
618
PJ_DEF(void) pj_scan_save_state( const pj_scanner *scanner, 
 
619
                                 pj_scan_state *state)
 
620
{
 
621
    state->curptr = scanner->curptr;
 
622
    state->line = scanner->line;
 
623
    state->start_line = scanner->start_line;
 
624
}
 
625
 
 
626
 
 
627
PJ_DEF(void) pj_scan_restore_state( pj_scanner *scanner, 
 
628
                                    pj_scan_state *state)
 
629
{
 
630
    scanner->curptr = state->curptr;
 
631
    scanner->line = state->line;
 
632
    scanner->start_line = state->start_line;
 
633
}
 
634
 
 
635