GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libform/fty_enum.c Lines: 0 79 0.0 %
Date: 2017-11-13 Branches: 0 88 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: fty_enum.c,v 1.11 2015/01/23 22:48:51 krw Exp $	*/
2
/****************************************************************************
3
 * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc.              *
4
 *                                                                          *
5
 * Permission is hereby granted, free of charge, to any person obtaining a  *
6
 * copy of this software and associated documentation files (the            *
7
 * "Software"), to deal in the Software without restriction, including      *
8
 * without limitation the rights to use, copy, modify, merge, publish,      *
9
 * distribute, distribute with modifications, sublicense, and/or sell       *
10
 * copies of the Software, and to permit persons to whom the Software is    *
11
 * furnished to do so, subject to the following conditions:                 *
12
 *                                                                          *
13
 * The above copyright notice and this permission notice shall be included  *
14
 * in all copies or substantial portions of the Software.                   *
15
 *                                                                          *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23
 *                                                                          *
24
 * Except as contained in this notice, the name(s) of the above copyright   *
25
 * holders shall not be used in advertising or otherwise to promote the     *
26
 * sale, use or other dealings in this Software without prior written       *
27
 * authorization.                                                           *
28
 ****************************************************************************/
29
30
/***************************************************************************
31
*                                                                          *
32
*  Author : Juergen Pfeifer                                                *
33
*                                                                          *
34
***************************************************************************/
35
36
#include "form.priv.h"
37
38
MODULE_ID("$Id: fty_enum.c,v 1.11 2015/01/23 22:48:51 krw Exp $")
39
40
typedef struct
41
  {
42
    char **kwds;
43
    int count;
44
    bool checkcase;
45
    bool checkunique;
46
  }
47
enumARG;
48
49
/*---------------------------------------------------------------------------
50
|   Facility      :  libnform
51
|   Function      :  static void *Make_Enum_Type( va_list * ap )
52
|
53
|   Description   :  Allocate structure for enumeration type argument.
54
|
55
|   Return Values :  Pointer to argument structure or NULL on error
56
+--------------------------------------------------------------------------*/
57
static void *
58
Make_Enum_Type(va_list *ap)
59
{
60
  enumARG *argp = typeMalloc(enumARG, 1);
61
62
  if (argp)
63
    {
64
      int cnt = 0;
65
      char **kp = (char **)0;
66
      int ccase, cunique;
67
68
      T((T_CREATE("enumARG %p"), argp));
69
      argp->kwds = va_arg(*ap, char **);
70
      ccase = va_arg(*ap, int);
71
      cunique = va_arg(*ap, int);
72
73
      argp->checkcase = ccase ? TRUE : FALSE;
74
      argp->checkunique = cunique ? TRUE : FALSE;
75
76
      kp = argp->kwds;
77
      while (kp && (*kp++))
78
	cnt++;
79
      argp->count = cnt;
80
    }
81
  return (void *)argp;
82
}
83
84
/*---------------------------------------------------------------------------
85
|   Facility      :  libnform
86
|   Function      :  static void *Copy_Enum_Type( const void * argp )
87
|
88
|   Description   :  Copy structure for enumeration type argument.
89
|
90
|   Return Values :  Pointer to argument structure or NULL on error.
91
+--------------------------------------------------------------------------*/
92
static void *
93
Copy_Enum_Type(const void *argp)
94
{
95
  enumARG *result = (enumARG *)0;
96
97
  if (argp)
98
    {
99
      const enumARG *ap = (const enumARG *)argp;
100
101
      result = typeMalloc(enumARG, 1);
102
103
      if (result)
104
	{
105
	  T((T_CREATE("enumARG %p"), result));
106
	  *result = *ap;
107
	}
108
    }
109
  return (void *)result;
110
}
111
112
/*---------------------------------------------------------------------------
113
|   Facility      :  libnform
114
|   Function      :  static void Free_Enum_Type( void * argp )
115
|
116
|   Description   :  Free structure for enumeration type argument.
117
|
118
|   Return Values :  -
119
+--------------------------------------------------------------------------*/
120
static void
121
Free_Enum_Type(void *argp)
122
{
123
  if (argp)
124
    free(argp);
125
}
126
127
#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
128
#define NOMATCH 0
129
#define PARTIAL 1
130
#define EXACT   2
131
132
/*---------------------------------------------------------------------------
133
|   Facility      :  libnform
134
|   Function      :  static int Compare(const unsigned char * s,
135
|                                       const unsigned char * buf,
136
|                                       bool  ccase )
137
|
138
|   Description   :  Check whether or not the text in 'buf' matches the
139
|                    text in 's', at least partial.
140
|
141
|   Return Values :  NOMATCH   - buffer doesn't match
142
|                    PARTIAL   - buffer matches partially
143
|                    EXACT     - buffer matches exactly
144
+--------------------------------------------------------------------------*/
145
static int
146
Compare(const unsigned char *s, const unsigned char *buf,
147
	bool ccase)
148
{
149
  SKIP_SPACE(buf);		/* Skip leading spaces in both texts */
150
  SKIP_SPACE(s);
151
152
  if (*buf == '\0')
153
    {
154
      return (((*s) != '\0') ? NOMATCH : EXACT);
155
    }
156
  else
157
    {
158
      if (ccase)
159
	{
160
	  while (*s++ == *buf)
161
	    {
162
	      if (*buf++ == '\0')
163
		return EXACT;
164
	    }
165
	}
166
      else
167
	{
168
	  while (toupper(*s++) == toupper(*buf))
169
	    {
170
	      if (*buf++ == '\0')
171
		return EXACT;
172
	    }
173
	}
174
    }
175
  /* At this location buf points to the first character where it no longer
176
     matches with s. So if only blanks are following, we have a partial
177
     match otherwise there is no match */
178
  SKIP_SPACE(buf);
179
  if (*buf)
180
    return NOMATCH;
181
182
  /* If it happens that the reference buffer is at its end, the partial
183
     match is actually an exact match. */
184
  return ((s[-1] != '\0') ? PARTIAL : EXACT);
185
}
186
187
/*---------------------------------------------------------------------------
188
|   Facility      :  libnform
189
|   Function      :  static bool Check_Enum_Field(
190
|                                      FIELD * field,
191
|                                      const void  * argp)
192
|
193
|   Description   :  Validate buffer content to be a valid enumeration value
194
|
195
|   Return Values :  TRUE  - field is valid
196
|                    FALSE - field is invalid
197
+--------------------------------------------------------------------------*/
198
static bool
199
Check_Enum_Field(FIELD *field, const void *argp)
200
{
201
  char **kwds = ((const enumARG *)argp)->kwds;
202
  bool ccase = ((const enumARG *)argp)->checkcase;
203
  bool unique = ((const enumARG *)argp)->checkunique;
204
  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
205
  char *s, *t, *p;
206
  int res;
207
208
  while (kwds && (s = (*kwds++)))
209
    {
210
      if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH)
211
	{
212
	  p = t = s;		/* t is at least a partial match */
213
	  if ((unique && res != EXACT))
214
	    {
215
	      while (kwds && (p = *kwds++))
216
		{
217
		  if ((res = Compare((unsigned char *)p, bp, ccase)) != NOMATCH)
218
		    {
219
		      if (res == EXACT)
220
			{
221
			  t = p;
222
			  break;
223
			}
224
		      else
225
			t = (char *)0;
226
		    }
227
		}
228
	    }
229
	  if (t)
230
	    {
231
	      set_field_buffer(field, 0, t);
232
	      return TRUE;
233
	    }
234
	  if (!p)
235
	    break;
236
	}
237
    }
238
  return FALSE;
239
}
240
241
static const char *dummy[] =
242
{(char *)0};
243
244
/*---------------------------------------------------------------------------
245
|   Facility      :  libnform
246
|   Function      :  static bool Next_Enum(FIELD * field,
247
|                                          const void * argp)
248
|
249
|   Description   :  Check for the next enumeration value
250
|
251
|   Return Values :  TRUE  - next value found and loaded
252
|                    FALSE - no next value loaded
253
+--------------------------------------------------------------------------*/
254
static bool
255
Next_Enum(FIELD *field, const void *argp)
256
{
257
  const enumARG *args = (const enumARG *)argp;
258
  char **kwds = args->kwds;
259
  bool ccase = args->checkcase;
260
  int cnt = args->count;
261
  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
262
263
  if (kwds)
264
    {
265
      while (cnt--)
266
	{
267
	  if (Compare((unsigned char *)(*kwds++), bp, ccase) == EXACT)
268
	    break;
269
	}
270
      if (cnt <= 0)
271
	kwds = args->kwds;
272
      if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
273
	{
274
	  set_field_buffer(field, 0, *kwds);
275
	  return TRUE;
276
	}
277
    }
278
  return FALSE;
279
}
280
281
/*---------------------------------------------------------------------------
282
|   Facility      :  libnform
283
|   Function      :  static bool Previous_Enum(
284
|                                          FIELD * field,
285
|                                          const void * argp)
286
|
287
|   Description   :  Check for the previous enumeration value
288
|
289
|   Return Values :  TRUE  - previous value found and loaded
290
|                    FALSE - no previous value loaded
291
+--------------------------------------------------------------------------*/
292
static bool
293
Previous_Enum(FIELD *field, const void *argp)
294
{
295
  const enumARG *args = (const enumARG *)argp;
296
  int cnt = args->count;
297
  char **kwds = &args->kwds[cnt - 1];
298
  bool ccase = args->checkcase;
299
  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
300
301
  if (kwds)
302
    {
303
      while (cnt--)
304
	{
305
	  if (Compare((unsigned char *)(*kwds--), bp, ccase) == EXACT)
306
	    break;
307
	}
308
309
      if (cnt <= 0)
310
	kwds = &args->kwds[args->count - 1];
311
312
      if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
313
	{
314
	  set_field_buffer(field, 0, *kwds);
315
	  return TRUE;
316
	}
317
    }
318
  return FALSE;
319
}
320
321
static FIELDTYPE typeENUM =
322
{
323
  _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
324
  1,				/* this is mutable, so we can't be const */
325
  (FIELDTYPE *)0,
326
  (FIELDTYPE *)0,
327
  Make_Enum_Type,
328
  Copy_Enum_Type,
329
  Free_Enum_Type,
330
  Check_Enum_Field,
331
  NULL,
332
  Next_Enum,
333
  Previous_Enum
334
};
335
336
NCURSES_EXPORT_VAR(FIELDTYPE *)
337
TYPE_ENUM = &typeENUM;
338
339
/* fty_enum.c ends here */