~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to helpers/testdfa.c

Update README.solaris.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * testdfa.c --- abstracted from gawk.
3
 
 *
4
 
 * gcc -I.. -I../support testdfa.c ../support/libsupport.a -lm -o testdfa
5
3
 */
6
4
 
7
 
/*
8
 
 * Copyright (C) 1986, 1988, 1989, 1991-2017, 2022, 2023,
9
 
 * the Free Software Foundation, Inc.
10
 
 *
 
5
/* 
 
6
 * Copyright (C) 1986, 1988, 1989, 1991-2013 the Free Software Foundation, Inc.
 
7
 * 
11
8
 * This file is part of GAWK, the GNU implementation of the
12
9
 * AWK Programming Language.
13
 
 *
 
10
 * 
14
11
 * GAWK is free software; you can redistribute it and/or modify
15
12
 * it under the terms of the GNU General Public License as published by
16
13
 * the Free Software Foundation; either version 3 of the License, or
17
14
 * (at your option) any later version.
18
 
 *
 
15
 * 
19
16
 * GAWK is distributed in the hope that it will be useful,
20
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
19
 * GNU General Public License for more details.
23
 
 *
 
20
 * 
24
21
 * You should have received a copy of the GNU General Public License
25
22
 * along with this program; if not, write to the Free Software
26
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
27
24
 */
28
25
 
29
 
#include <config.h>
30
 
 
31
26
#include <stdio.h>
32
27
#include <ctype.h>
33
28
#include <errno.h>
45
40
#include <sys/stat.h>
46
41
 
47
42
 
48
 
#undef _Noreturn
49
43
#define _Noreturn
50
 
/*#define _GL_ATTRIBUTE_PURE */
51
44
#include "dfa.h"
52
 
#include "localeinfo.h"
53
45
 
54
46
const char *regexflags2str(int flags);
55
47
char *databuf(int fd);
56
48
const char * reflags2str(int flagval);
57
49
int parse_escape(const char **string_ptr);
58
 
char *setup_pattern(const char *pattern, size_t *len);
 
50
char *setup_pattern(const char *pattern, size_t len);
59
51
char casetable[];
60
52
 
61
53
reg_syntax_t syn;
77
69
 
78
70
int main(int argc, char **argv)
79
71
{
80
 
        int c, ret;
81
 
        bool try_backref;
 
72
        int c, ret, try_backref;
82
73
        struct re_pattern_buffer pat;
83
74
        struct re_registers regs;
84
75
        struct dfa *dfareg;
91
82
        char save;
92
83
        size_t count = 0;
93
84
        char *place;
94
 
        bool not_bol = false;
95
 
        struct localeinfo localeinfo;
96
 
        int start = 0;
97
 
 
98
 
        pma_init(1, NULL);
99
85
 
100
86
        if (argc < 2)
101
87
                usage(argv[0]);
107
93
        syn = RE_SYNTAX_GNU_AWK;
108
94
 
109
95
        /* parse options, update syntax, ignorecase */
110
 
        while ((c = getopt(argc, argv, "bpits:")) != -1) {
 
96
        while ((c = getopt(argc, argv, "pit")) != -1) {
111
97
                switch (c) {
112
 
                case 'b':
113
 
                        not_bol = true;
114
 
                        break;
115
98
                case 'i':
116
99
                        ignorecase = true;
117
100
                        break;
121
104
                case 't':
122
105
                        syn = RE_SYNTAX_AWK;
123
106
                        break;
124
 
                case 's':
125
 
                        sscanf(optarg, "%d", & start);
126
 
                        break;
127
107
                case '?':
128
108
                default:
129
109
                        usage(argv[0]);
134
114
        if (optind == argc)
135
115
                usage(argv[0]);
136
116
 
137
 
        if (start < 0 || start > strlen(argv[optind])) {
138
 
                fprintf(stderr, "%s: start index %d is out of range\n", argv[0], start);
139
 
                exit(EXIT_FAILURE);
140
 
        }
141
 
 
142
117
        pattern = argv[optind];
143
118
        len = strlen(pattern);
144
119
 
151
126
        printf("Ignorecase: %s\nSyntax: %s\n",
152
127
                        (ignorecase ? "true" : "false"),
153
128
                        reflags2str(syn));
154
 
        printf("Pattern: /%s/, len = %lu\n", pattern, len);
 
129
        printf("Pattern: /%s/\n", pattern);
155
130
 
156
 
        pattern = setup_pattern(pattern, & len);
157
 
        printf("After setup_pattern(), len = %lu\n", len);
 
131
        pattern = setup_pattern(pattern, len);
 
132
        len = strlen(pattern);
158
133
 
159
134
        pat.fastmap = (char *) malloc(256);
160
135
        if (pat.fastmap == NULL) {
176
151
                pat.translate = NULL;
177
152
                syn &= ~RE_ICASE;
178
153
        }
179
 
        pat.allocated = 0;
180
154
 
181
155
 
182
156
        dfa_syn = syn;
183
157
        if (ignorecase)
184
158
                dfa_syn |= RE_ICASE;
 
159
        dfasyntax(dfa_syn, ignorecase, '\n');
185
160
        re_set_syntax(syn);
186
161
 
187
162
        if ((rerr = re_compile_pattern(pattern, len, & pat)) != NULL) {
192
167
 
193
168
        /* gack. this must be done *after* re_compile_pattern */
194
169
        pat.newline_anchor = false; /* don't get \n in middle of string */
195
 
        pat.not_bol = not_bol;
196
170
 
197
171
        dfareg = dfaalloc();
198
 
        init_localeinfo(&localeinfo);
199
 
        dfasyntax(dfareg, &localeinfo, dfa_syn, DFA_ANCHOR);
200
 
 
201
172
        printf("Calling dfacomp(%s, %d, %p, true)\n",
202
173
                        pattern, (int) len, dfareg);
203
174
 
205
176
 
206
177
 
207
178
        data = databuf(STDIN_FILENO);
208
 
        len = strlen(data);
209
 
 
210
 
        if (data[len-1] == '\n')
211
 
                data[--len] = '\0';     // clobber newline
212
 
 
213
 
        printf("data: <%s>\n", data);
214
179
 
215
180
        /* run the regex matcher */
216
 
        ret = re_search(& pat, data, len, start, len, NULL);
217
 
        printf("re_search with NULL returned position %d (%s)\n", ret, (ret >= 0) ? "true" : "false");
218
 
#if 0
219
 
        printf("pat.allocated = %ld\n", pat.allocated);
220
 
        printf("pat.used = %ld\n", pat.used);
221
 
        printf("pat.syntax = %ld\n", pat.syntax);
222
 
        printf("pat.re_nsub = %ld\n", pat.re_nsub);
223
 
        printf("pat.can_be_null = %d\n", pat.can_be_null);
224
 
        printf("pat.regs_allocated = %d\n", pat.regs_allocated);
225
 
        printf("pat.fastmap_accurate = %d\n", pat.fastmap_accurate);
226
 
        printf("pat.no_sub = %d\n", pat.no_sub);
227
 
        printf("pat.not_bol = %d\n", pat.not_bol);
228
 
        printf("pat.not_eol = %d\n", pat.not_eol);
229
 
        printf("pat.newline_anchor = %d\n", pat.newline_anchor);
230
 
#endif
231
 
 
232
 
        ret = re_search(& pat, data, len, start, len, &regs);
 
181
        ret = re_search(& pat, data, len, 0, len, NULL);
233
182
        printf("re_search returned position %d (%s)\n", ret, (ret >= 0) ? "true" : "false");
234
 
#if 0
235
 
        printf("pat.allocated = %ld\n", pat.allocated);
236
 
        printf("pat.used = %ld\n", pat.used);
237
 
        printf("pat.syntax = %ld\n", pat.syntax);
238
 
        printf("pat.re_nsub = %ld\n", pat.re_nsub);
239
 
        printf("pat.can_be_null = %d\n", pat.can_be_null);
240
 
        printf("pat.regs_allocated = %d\n", pat.regs_allocated);
241
 
        printf("pat.fastmap_accurate = %d\n", pat.fastmap_accurate);
242
 
        printf("pat.no_sub = %d\n", pat.no_sub);
243
 
        printf("pat.not_bol = %d\n", pat.not_bol);
244
 
        printf("pat.not_eol = %d\n", pat.not_eol);
245
 
        printf("pat.newline_anchor = %d\n", pat.newline_anchor);
246
 
#endif
247
 
        printf("pat.re_nsub = %d\n", pat.re_nsub);
248
 
        for (int i = 0; i <= pat.re_nsub; i++)
249
 
                printf("\treg[%d].so = %d, reg[%d].eo = %d\n", i, regs.start[i], i, regs.end[i]);
250
183
 
251
184
        /* run the dfa matcher */
252
185
        /*
258
191
                                &count, &try_backref);
259
192
        data[len] = save;
260
193
 
261
 
        if (place == NULL)
262
 
                printf("dfaexec returned NULL\n");
263
 
        else
264
 
                printf("dfaexec returned %ld (%.3s)\n", place - data, place);
 
194
        printf("dfaexec returned %p (%.3s)\n", place, place);
265
195
 
266
196
        /* release storage */
267
197
        regfree(& pat);
401
331
        return buf;
402
332
}
403
333
 
 
334
/* xmalloc --- for dfa.c */
 
335
 
 
336
void *
 
337
xmalloc(size_t bytes)
 
338
{
 
339
        void *p = malloc(bytes);
 
340
 
 
341
        if (p == NULL) {
 
342
                fprintf(stderr, "xmalloc: malloc failed: %s\n", strerror(errno));
 
343
                exit(EXIT_FAILURE);
 
344
        }
 
345
 
 
346
        return p;
 
347
}
 
348
 
404
349
/* r_fatal --- print a fatal error message. also for dfa.c */
405
350
 
406
351
void
418
363
/* setup_pattern --- do what gawk does with the pattern string */
419
364
 
420
365
char *
421
 
setup_pattern(const char *pattern, size_t *len)
 
366
setup_pattern(const char *pattern, size_t len)
422
367
{
423
368
        size_t is_multibyte = 0;
424
369
        int c, c2;
425
 
        size_t buflen;
 
370
        size_t buflen = 0;
426
371
        mbstate_t mbs;
427
372
        bool has_anchor = false;
428
 
        char *buf;
 
373
        char *buf = NULL;
429
374
        char *dest;
430
375
        const char *src, *end;
431
376
 
432
377
        memset(& mbs, 0, sizeof(mbs));
433
378
 
434
379
        src = pattern;
435
 
        end = pattern + *len;
 
380
        end = pattern + len;
436
381
 
437
382
        /* Handle escaped characters first. */
438
383
 
439
384
        /*
440
385
         * Build a copy of the string (in buf) with the
441
386
         * escaped characters translated, and generate the regex
442
 
         * from that.
 
387
         * from that. 
443
388
         */
444
 
        buf = (char *) malloc(*len + 1);
445
389
        if (buf == NULL) {
446
 
                fprintf(stderr, "%s: malloc failed\n", __func__);
447
 
                exit(EXIT_FAILURE);
 
390
                buf = (char *) malloc(len + 2);
 
391
                if (buf == NULL) {
 
392
                        fprintf(stderr, "%s: malloc failed\n", __func__);
 
393
                        exit(EXIT_FAILURE);
 
394
                }
 
395
                buflen = len;
 
396
        } else if (len > buflen) {
 
397
                buf = (char *) realloc(buf, len + 2);
 
398
                if (buf == NULL) {
 
399
                        fprintf(stderr, "%s: realloc failed\n", __func__);
 
400
                        exit(EXIT_FAILURE);
 
401
                }
 
402
                buflen = len;
448
403
        }
449
 
        buflen = *len;
450
404
        dest = buf;
451
405
 
452
406
        while (src < end) {
533
487
        } /* while */
534
488
 
535
489
        *dest = '\0';
536
 
        *len = dest - buf;
 
490
        len = dest - buf;
537
491
 
538
492
        return buf;
539
493
}
543
497
 *
544
498
 * Parse a C escape sequence.  STRING_PTR points to a variable containing a
545
499
 * pointer to the string to parse.  That pointer is updated past the
546
 
 * characters we use.  The value of the escape sequence is returned.
 
500
 * characters we use.  The value of the escape sequence is returned. 
547
501
 *
548
502
 * A negative value means the sequence \ newline was seen, which is supposed to
549
 
 * be equivalent to nothing at all.
 
503
 * be equivalent to nothing at all. 
550
504
 *
551
505
 * If \ is followed by a null character, we return a negative value and leave
552
 
 * the string pointer pointing at the null character.
 
506
 * the string pointer pointing at the null character. 
553
507
 *
554
508
 * If \ is followed by 000, we return 0 and leave the string pointer after the
555
 
 * zeros.  A value of 0 does not mean end of string.
 
509
 * zeros.  A value of 0 does not mean end of string.  
556
510
 *
557
511
 * POSIX doesn't allow \x.
558
512
 */
641
595
#ifdef C
642
596
#undef C
643
597
#endif
644
 
#define C(c) ((char)c)
 
598
#define C(c) ((char)c)  
645
599
/*
646
600
 * This table is used by the regexp routines to do case independent
647
601
 * matching. Basically, every ascii character maps to itself, except
709
663
        C('\360'), C('\361'), C('\362'), C('\363'), C('\364'), C('\365'), C('\366'), C('\367'),
710
664
        C('\370'), C('\371'), C('\372'), C('\373'), C('\374'), C('\375'), C('\376'), C('\377'),
711
665
};
712
 
#elif defined(USE_EBCDIC)
 
666
#elif 'a' == 0x81 /* it's EBCDIC */
713
667
char casetable[] = {
714
668
 /*00  NU    SH    SX    EX    PF    HT    LC    DL */
715
669
      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
781
735
#endif
782
736
 
783
737
#undef C
 
738
 
 
739
#ifdef GREP_DFA /* not needed for gawk */
 
740
/* xalloc.h -- malloc with out-of-memory checking
 
741
 
 
742
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 
743
   2000, 2003, 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
 
744
   Inc.
 
745
 
 
746
   This program is free software: you can redistribute it and/or modify
 
747
   it under the terms of the GNU General Public License as published by
 
748
   the Free Software Foundation; either version 3 of the License, or
 
749
   (at your option) any later version.
 
750
 
 
751
   This program is distributed in the hope that it will be useful,
 
752
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
753
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
754
   GNU General Public License for more details.
 
755
 
 
756
   You should have received a copy of the GNU General Public License
 
757
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
758
 
 
759
#ifndef XALLOC_H_
 
760
# define XALLOC_H_
 
761
 
 
762
# include <stddef.h>
 
763
 
 
764
 
 
765
# ifdef __cplusplus
 
766
extern "C" {
 
767
# endif
 
768
 
 
769
 
 
770
# ifndef __attribute__
 
771
#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
 
772
#   define __attribute__(x)
 
773
#  endif
 
774
# endif
 
775
 
 
776
# ifndef ATTRIBUTE_NORETURN
 
777
#  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
 
778
# endif
 
779
 
 
780
# ifndef ATTRIBUTE_MALLOC
 
781
#  if __GNUC__ >= 3
 
782
#   define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
 
783
#  else
 
784
#   define ATTRIBUTE_MALLOC
 
785
#  endif
 
786
# endif
 
787
 
 
788
/* This function is always triggered when memory is exhausted.
 
789
   It must be defined by the application, either explicitly
 
790
   or by using gnulib's xalloc-die module.  This is the
 
791
   function to call when one wants the program to die because of a
 
792
   memory allocation failure.  */
 
793
extern void xalloc_die (void);
 
794
 
 
795
void *xmalloc (size_t s) ATTRIBUTE_MALLOC;
 
796
void *xzalloc (size_t s) ATTRIBUTE_MALLOC;
 
797
void *xcalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
 
798
void *xrealloc (void *p, size_t s);
 
799
void *x2realloc (void *p, size_t *pn);
 
800
void *xmemdup (void const *p, size_t s) ATTRIBUTE_MALLOC;
 
801
char *xstrdup (char const *str) ATTRIBUTE_MALLOC;
 
802
 
 
803
/* Return 1 if an array of N objects, each of size S, cannot exist due
 
804
   to size arithmetic overflow.  S must be positive and N must be
 
805
   nonnegative.  This is a macro, not an inline function, so that it
 
806
   works correctly even when SIZE_MAX < N.
 
807
 
 
808
   By gnulib convention, SIZE_MAX represents overflow in size
 
809
   calculations, so the conservative dividend to use here is
 
810
   SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
 
811
   However, malloc (SIZE_MAX) fails on all known hosts where
 
812
   sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
 
813
   exactly-SIZE_MAX allocations on such hosts; this avoids a test and
 
814
   branch when S is known to be 1.  */
 
815
# define xalloc_oversized(n, s) \
 
816
    ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
 
817
 
 
818
 
 
819
/* In the following macros, T must be an elementary or structure/union or
 
820
   typedef'ed type, or a pointer to such a type.  To apply one of the
 
821
   following macros to a function pointer or array type, you need to typedef
 
822
   it first and use the typedef name.  */
 
823
 
 
824
/* Allocate an object of type T dynamically, with error checking.  */
 
825
/* extern t *XMALLOC (typename t); */
 
826
# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
 
827
 
 
828
/* Allocate memory for N elements of type T, with error checking.  */
 
829
/* extern t *XNMALLOC (size_t n, typename t); */
 
830
# define XNMALLOC(n, t) \
 
831
    ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
 
832
 
 
833
/* Allocate an object of type T dynamically, with error checking,
 
834
   and zero it.  */
 
835
/* extern t *XZALLOC (typename t); */
 
836
# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
 
837
 
 
838
/* Allocate memory for N elements of type T, with error checking,
 
839
   and zero it.  */
 
840
/* extern t *XCALLOC (size_t n, typename t); */
 
841
# define XCALLOC(n, t) \
 
842
    ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
 
843
 
 
844
/*
 
845
 * Gawk uses this file only to keep dfa.c happy.
 
846
 * We're therefore safe in manually defining HAVE_INLINE to
 
847
 * make the !@#$%^&*() thing just work.
 
848
 */
 
849
#ifdef GAWK
 
850
#define HAVE_INLINE     1       /* so there. nyah, nyah, nyah. */
 
851
#endif
 
852
 
 
853
# if HAVE_INLINE
 
854
#  define static_inline static inline
 
855
# else
 
856
void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
 
857
void *xnrealloc (void *p, size_t n, size_t s);
 
858
void *x2nrealloc (void *p, size_t *pn, size_t s);
 
859
char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
 
860
# endif
 
861
 
 
862
 
 
863
/* Allocate an array of N objects, each with S bytes of memory,
 
864
   dynamically, with error checking.  S must be nonzero.  */
 
865
 
 
866
void *
 
867
xnmalloc (size_t n, size_t s)
 
868
{
 
869
  if (xalloc_oversized (n, s))
 
870
    xalloc_die ();
 
871
  return xmalloc (n * s);
 
872
}
 
873
 
 
874
/* Allocate an array of N objects, each with S bytes of memory,
 
875
   dynamically, with error checking.  S must be nonzero.
 
876
   Clear the contents afterwards.  */
 
877
 
 
878
void *
 
879
xcalloc(size_t nmemb, size_t size)
 
880
{
 
881
  void *p = xmalloc (nmemb * size);
 
882
  memset(p, '\0', nmemb * size);
 
883
  return p;
 
884
}
 
885
 
 
886
/* Reallocate a pointer to a new size, with error checking. */
 
887
 
 
888
void *
 
889
xrealloc(void *p, size_t size)
 
890
{
 
891
   void *new_p = realloc(p, size);
 
892
   if (new_p ==  0)
 
893
     xalloc_die ();
 
894
 
 
895
   return new_p;
 
896
}
 
897
 
 
898
/* xalloc_die --- fatal error message when malloc fails, needed by dfa.c */
 
899
 
 
900
void
 
901
xalloc_die (void)
 
902
{
 
903
        r_fatal("xalloc: malloc failed: %s"), strerror(errno);
 
904
}
 
905
 
 
906
/* Clone an object P of size S, with error checking.  There's no need
 
907
   for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
 
908
   need for an arithmetic overflow check.  */
 
909
 
 
910
void *
 
911
xmemdup (void const *p, size_t s)
 
912
{
 
913
  return memcpy (xmalloc (s), p, s);
 
914
}
 
915
 
 
916
/* Change the size of an allocated block of memory P to an array of N
 
917
   objects each of S bytes, with error checking.  S must be nonzero.  */
 
918
 
 
919
void *
 
920
xnrealloc (void *p, size_t n, size_t s)
 
921
{
 
922
  if (xalloc_oversized (n, s))
 
923
    xalloc_die ();
 
924
  return xrealloc (p, n * s);
 
925
}
 
926
 
 
927
/* If P is null, allocate a block of at least *PN such objects;
 
928
   otherwise, reallocate P so that it contains more than *PN objects
 
929
   each of S bytes.  *PN must be nonzero unless P is null, and S must
 
930
   be nonzero.  Set *PN to the new number of objects, and return the
 
931
   pointer to the new block.  *PN is never set to zero, and the
 
932
   returned pointer is never null.
 
933
 
 
934
   Repeated reallocations are guaranteed to make progress, either by
 
935
   allocating an initial block with a nonzero size, or by allocating a
 
936
   larger block.
 
937
 
 
938
   In the following implementation, nonzero sizes are increased by a
 
939
   factor of approximately 1.5 so that repeated reallocations have
 
940
   O(N) overall cost rather than O(N**2) cost, but the
 
941
   specification for this function does not guarantee that rate.
 
942
 
 
943
   Here is an example of use:
 
944
 
 
945
     int *p = NULL;
 
946
     size_t used = 0;
 
947
     size_t allocated = 0;
 
948
 
 
949
     void
 
950
     append_int (int value)
 
951
       {
 
952
         if (used == allocated)
 
953
           p = x2nrealloc (p, &allocated, sizeof *p);
 
954
         p[used++] = value;
 
955
       }
 
956
 
 
957
   This causes x2nrealloc to allocate a block of some nonzero size the
 
958
   first time it is called.
 
959
 
 
960
   To have finer-grained control over the initial size, set *PN to a
 
961
   nonzero value before calling this function with P == NULL.  For
 
962
   example:
 
963
 
 
964
     int *p = NULL;
 
965
     size_t used = 0;
 
966
     size_t allocated = 0;
 
967
     size_t allocated1 = 1000;
 
968
 
 
969
     void
 
970
     append_int (int value)
 
971
       {
 
972
         if (used == allocated)
 
973
           {
 
974
             p = x2nrealloc (p, &allocated1, sizeof *p);
 
975
             allocated = allocated1;
 
976
           }
 
977
         p[used++] = value;
 
978
       }
 
979
 
 
980
   */
 
981
 
 
982
void *
 
983
x2nrealloc (void *p, size_t *pn, size_t s)
 
984
{
 
985
  size_t n = *pn;
 
986
 
 
987
  if (! p)
 
988
    {
 
989
      if (! n)
 
990
        {
 
991
          /* The approximate size to use for initial small allocation
 
992
             requests, when the invoking code specifies an old size of
 
993
             zero.  64 bytes is the largest "small" request for the
 
994
             GNU C library malloc.  */
 
995
          enum { DEFAULT_MXFAST = 64 };
 
996
 
 
997
          n = DEFAULT_MXFAST / s;
 
998
          n += !n;
 
999
        }
 
1000
    }
 
1001
  else
 
1002
    {
 
1003
      /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
 
1004
         Check for overflow, so that N * S stays in size_t range.
 
1005
         The check is slightly conservative, but an exact check isn't
 
1006
         worth the trouble.  */
 
1007
      if ((size_t) -1 / 3 * 2 / s <= n)
 
1008
        xalloc_die ();
 
1009
      n += (n + 1) / 2;
 
1010
    }
 
1011
 
 
1012
  *pn = n;
 
1013
  return xrealloc (p, n * s);
 
1014
}
 
1015
 
 
1016
/* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
 
1017
   except it returns char *.  */
 
1018
 
 
1019
char *
 
1020
xcharalloc (size_t n)
 
1021
{
 
1022
  return XNMALLOC (n, char);
 
1023
}
 
1024
 
 
1025
/* Allocate S bytes of zeroed memory dynamically, with error checking.
 
1026
   There's no need for xnzalloc (N, S), since it would be equivalent
 
1027
   to xcalloc (N, S).  */
 
1028
 
 
1029
void *
 
1030
xzalloc (size_t s)
 
1031
{
 
1032
  return memset (xmalloc (s), 0, s);
 
1033
}
 
1034
 
 
1035
# endif
 
1036
 
 
1037
# ifdef __cplusplus
 
1038
}
 
1039
 
 
1040
/* C++ does not allow conversions from void * to other pointer types
 
1041
   without a cast.  Use templates to work around the problem when
 
1042
   possible.  */
 
1043
 
 
1044
template <typename T> inline T *
 
1045
xrealloc (T *p, size_t s)
 
1046
{
 
1047
  return (T *) xrealloc ((void *) p, s);
 
1048
}
 
1049
 
 
1050
template <typename T> inline T *
 
1051
xnrealloc (T *p, size_t n, size_t s)
 
1052
{
 
1053
  return (T *) xnrealloc ((void *) p, n, s);
 
1054
}
 
1055
 
 
1056
template <typename T> inline T *
 
1057
x2realloc (T *p, size_t *pn)
 
1058
{
 
1059
  return (T *) x2realloc ((void *) p, pn);
 
1060
}
 
1061
 
 
1062
template <typename T> inline T *
 
1063
x2nrealloc (T *p, size_t *pn, size_t s)
 
1064
{
 
1065
  return (T *) x2nrealloc ((void *) p, pn, s);
 
1066
}
 
1067
 
 
1068
template <typename T> inline T *
 
1069
xmemdup (T const *p, size_t s)
 
1070
{
 
1071
  return (T *) xmemdup ((void const *) p, s);
 
1072
}
 
1073
 
 
1074
 
 
1075
 
 
1076
#endif /* !XALLOC_H_ */
 
1077
#endif /* GREP_DFA */