The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / buildroot-2015.05 / package / uclibc / 0.9.33.2 / 0030-stdio-implement-assignment-allocation-m-character.patch
1 From 050cd6971f92c2337bc506043dfcf1395dd5d622 Mon Sep 17 00:00:00 2001
2 From: Mike Frysinger <vapier@gentoo.org>
3 Date: Sun, 6 May 2012 03:50:44 -0400
4 Subject: [PATCH] stdio: implement assignment-allocation "m" character
5
6 The latest POSIX spec introduces a "m" character to allocate buffers for
7 the user when using scanf type functions.  This is like the old glibc "a"
8 flag, but now standardized.  With packages starting to use these, we need
9 to implement it.
10
11 for example:
12         char *s;
13         sscanf("foo", "%ms", &s);
14         printf("%s\n", s);
15         free(s);
16 This will automatically allocate storage for "s", read in "foo" to it,
17 and then display it.
18
19 I'm not terribly familiar with the stdio layer, so this could be wrong.
20 But it seems to work for me.
21
22 Signed-off-by: Mike Frysinger <vapier@gentoo.org>
23 ---
24  extra/Configs/Config.in |   13 ---------
25  libc/stdio/_scanf.c     |   68 +++++++++++++++++++++++++++--------------------
26  2 files changed, 39 insertions(+), 42 deletions(-)
27
28 diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
29 index 1060729..c2f2fc7 100644
30 --- a/extra/Configs/Config.in
31 +++ b/extra/Configs/Config.in
32 @@ -1590,19 +1590,6 @@ config UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS
33  
34           Most people will answer 9.
35  
36 -
37 -config UCLIBC_HAS_SCANF_GLIBC_A_FLAG
38 -       bool "Support glibc's 'a' flag for scanf string conversions (not implemented)"
39 -       help
40 -         NOTE!!!  Currently Not Implemented!!! Just A Place Holder!!  NOTE!!!
41 -         NOTE!!!  Conflicts with an ANSI/ISO C99 scanf flag!!         NOTE!!!
42 -
43 -         Answer Y to enable support for glibc's 'a' flag for the scanf string
44 -         conversions '%s', '%[', '%ls', '%l[', and '%S'.  This is used to
45 -         auto-allocate sufficient memory to hold the data retrieved.
46 -
47 -         Most people will answer N.
48 -
49  choice
50         prompt "Stdio buffer size"
51         default UCLIBC_HAS_STDIO_BUFSIZ_4096
52 diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c
53 index f38e72b..952853c 100644
54 --- a/libc/stdio/_scanf.c
55 +++ b/libc/stdio/_scanf.c
56 @@ -77,14 +77,6 @@
57  #include <bits/uClibc_fpmax.h>
58  #endif /* __UCLIBC_HAS_FLOATS__ */
59  
60 -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
61 -#ifdef L_vfscanf
62 -/* only emit this once */
63 -#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented!
64 -#endif
65 -#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
66 -#endif
67 -
68  #undef __STDIO_HAS_VSSCANF
69  #if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
70  #define __STDIO_HAS_VSSCANF 1
71 @@ -433,8 +425,9 @@ libc_hidden_def(vswscanf)
72  
73  
74  /* float layout          0123456789012345678901  repeat n for "l[" */
75 -#define SPEC_CHARS             "npxXoudifFeEgGaACSncs["
76 -/*                       npxXoudif eEgG  CS cs[ */
77 +#define SPEC_CHARS             "npxXoudifFeEgGaACSnmcs["
78 +/*                       npxXoudif eEgG  CS  cs[ */
79 +/* NOTE: the 'm' flag must come before any convs that support it */
80  
81  /* NOTE: Ordering is important!  In particular, CONV_LEFTBRACKET
82   * must immediately precede CONV_c. */
83 @@ -444,7 +437,7 @@ enum {
84         CONV_p,
85         CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i,
86         CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A,
87 -       CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket,
88 +       CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_m, CONV_c, CONV_s, CONV_leftbracket,
89         CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */
90  };
91  
92 @@ -474,7 +467,7 @@ enum {
93         FLAG_SURPRESS   =   0x10,       /* MUST BE 1ST!!  See DO_FLAGS. */
94         FLAG_THOUSANDS  =       0x20,
95         FLAG_I18N               =       0x40,   /* only works for d, i, u */
96 -       FLAG_MALLOC     =   0x80,       /* only works for s, S, and [ (and l[)*/
97 +       FLAG_MALLOC     =   0x80,       /* only works for c, s, S, and [ (and l[)*/
98  };
99  
100  
101 @@ -491,7 +484,7 @@ enum {
102         /* fFeEgGaA */  (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \
103         /* C */                 (   0|FLAG_SURPRESS), \
104         /* S and l[ */  (   0|FLAG_SURPRESS|FLAG_MALLOC), \
105 -       /* c */                 (0x04|FLAG_SURPRESS), \
106 +       /* c */                 (0x04|FLAG_SURPRESS|FLAG_MALLOC), \
107         /* s and [ */   (0x04|FLAG_SURPRESS|FLAG_MALLOC), \
108  }
109  
110 @@ -904,17 +897,17 @@ int attribute_hidden __psfs_parse_spec(register psfs_t *psfs)
111                 if (*psfs->fmt == *p) {
112                         int p_m_spec_chars = p - spec_chars;
113  
114 -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
115 -#error implement gnu a flag
116 -                       if ((*p == 'a')
117 -                               && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's'))
118 -                               ) {             /* Assumes ascii for 's' and 'S' test. */
119 -                               psfs->flags |= FLAG_MALLOC;
120 +                       if (*p == 'm' &&
121 +                               (psfs->fmt[1] == '[' || psfs->fmt[1] == 'c' ||
122 +                                /* Assumes ascii for 's' and 'S' test. */
123 +                                (psfs->fmt[1] | 0x20) == 's'))
124 +                       {
125 +                               if (psfs->store)
126 +                                       psfs->flags |= FLAG_MALLOC;
127                                 ++psfs->fmt;
128                                 ++p;
129 -                               continue; /* The related conversions follow 'a'. */
130 +                               continue; /* The related conversions follow 'm'. */
131                         }
132 -#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */
133  
134                         for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {}
135                         if (((psfs->dataargtype >> 8) | psfs->flags)
136 @@ -1265,12 +1258,6 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)
137                                 while (*wf && __isascii(*wf) && (b < buf + sizeof(buf) - 1)) {
138                                         *b++ = *wf++;
139                                 }
140 -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
141 -#error this is wrong... we need to ched in __psfs_parse_spec instead since this checks last char in buffer and conversion my have stopped before it.
142 -                               if ((*b == 'a') && ((*wf == '[') || ((*wf|0x20) == 's'))) {
143 -                                       goto DONE;      /* Spec was excessively long. */
144 -                               }
145 -#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */
146                                 *b = 0;
147                                 if (b == buf) { /* Bad conversion specifier! */
148                                         goto DONE;
149 @@ -1390,13 +1377,36 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)
150                                 }
151  
152                                 if (psfs.conv_num == CONV_s) {
153 +                                       /* We might have to handle the allocation ourselves */
154 +                                       int len;
155 +                                       /* With 'm', we actually got a pointer to a pointer */
156 +                                       unsigned char **ptr = (void *)b;
157 +
158 +                                       i = 0;
159 +                                       if (psfs.flags & FLAG_MALLOC) {
160 +                                               len = 0;
161 +                                               b = NULL;
162 +                                       } else
163 +                                               len = -1;
164 +
165                                         /* Yes, believe it or not, a %s conversion can store nuls. */
166                                         while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) {
167                                                 zero_conversions = 0;
168 -                                               *b = sc.cc;
169 -                                               b += psfs.store;
170 +                                               if (i == len) {
171 +                                                       /* Pick a size that won't trigger a lot of
172 +                                                        * mallocs early on ... */
173 +                                                       len += 256;
174 +                                                       b = realloc(b, len + 1);
175 +                                               }
176 +                                               b[i] = sc.cc;
177 +                                               i += psfs.store;
178                                                 fail = 0;
179                                         }
180 +
181 +                                       if (psfs.flags & FLAG_MALLOC)
182 +                                               *ptr = b;
183 +                                       /* The code below takes care of terminating NUL */
184 +                                       b += i;
185                                 } else {
186  #ifdef __UCLIBC_HAS_WCHAR__
187                                         assert((psfs.conv_num == CONV_LEFTBRACKET) || \
188 -- 
189 1.7.10.4
190