1 /* $NetBSD: type_integer.c,v 1.4 2001/06/13 10:45:59 wiz Exp $ */ 2 3 /*- 4 * Copyright (c) 1998-1999 Brett Lymn 5 * (blymn@baea.com.au, brett_lymn@yahoo.com.au) 6 * All rights reserved. 7 * 8 * This code has been donated to The NetBSD Foundation by the Author. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * 30 */ 31 32 #include <stdlib.h> 33 #include <strings.h> 34 #include <ctype.h> 35 #include "form.h" 36 #include "internals.h" 37 38 /* 39 * The integer type handling. 40 */ 41 42 typedef struct 43 { 44 unsigned precision; 45 long min; 46 long max; 47 } integer_args; 48 49 /* 50 * Create the integer arguments structure from the given args. Return NULL 51 * if the call fails, otherwise return a pointer to the structure allocated. 52 */ 53 static char * 54 create_integer_args(va_list *args) 55 { 56 integer_args *new; 57 58 new = (integer_args *) malloc(sizeof(integer_args)); 59 60 if (new != NULL) { 61 new->precision = va_arg(*args, unsigned); 62 new->min = va_arg(*args, long); 63 new->max = va_arg(*args, long); 64 } 65 66 return (void *) new; 67 } 68 69 /* 70 * Copy the the integer argument structure. 71 */ 72 static char * 73 copy_integer_args(char *args) 74 { 75 integer_args *new; 76 77 new = (integer_args *) malloc(sizeof(integer_args)); 78 79 if (new != NULL) 80 bcopy(args, new, sizeof(integer_args)); 81 82 return (void *) new; 83 } 84 85 /* 86 * Free the allocated storage associated with the type arguments. 87 */ 88 static void 89 free_integer_args(char *args) 90 { 91 if (args != NULL) 92 free(args); 93 } 94 95 /* 96 * Check the contents of the field buffer are digits only. 97 */ 98 static int 99 integer_check_field(FIELD *field, char *args) 100 { 101 int cur; 102 long number, max, min; 103 int precision; 104 char *buf, *new_buf; 105 106 if (args == NULL) 107 return FALSE; 108 109 precision = ((integer_args *) (void *) field->args)->precision; 110 min = ((integer_args *) (void *) field->args)->min; 111 max = ((integer_args *) (void *) field->args)->max; 112 113 buf = args; 114 cur = 0; 115 116 /* skip leading white space */ 117 while ((buf[cur] != '\0') 118 && ((buf[cur] == ' ') || (buf[cur] == '\t'))) 119 cur++; 120 121 /* no good if we have hit the end */ 122 if (buf[cur] == '\0') 123 return FALSE; 124 125 /* find the end of the digits but allow a leading + or - sign */ 126 if ((buf[cur] == '-') || (buf[cur] == '+')) 127 cur++; 128 129 while((buf[cur] != '\0') && isdigit(buf[cur])) 130 cur++; 131 132 /* check there is only trailing whitespace */ 133 while ((buf[cur] != '\0') 134 && ((buf[cur] == ' ') || (buf[cur] == '\t'))) 135 cur++; 136 137 /* no good if we are not at the end of the string */ 138 if (buf[cur] != '\0') 139 return FALSE; 140 141 /* convert and range check the number...*/ 142 number = atol(buf); 143 if ((min > max) || ((number < min) || (number > max))) 144 return FALSE; 145 146 if (asprintf(&new_buf, "%.*ld", precision, number) < 0) 147 return FALSE; 148 149 /* re-set the field buffer to be the reformatted numeric */ 150 set_field_buffer(field, 0, new_buf); 151 152 free(new_buf); 153 154 /* otherwise all was ok */ 155 return TRUE; 156 } 157 158 /* 159 * Check the given character is numeric, return TRUE if it is. 160 */ 161 static int 162 integer_check_char(/* ARGSUSED1 */ int c, char *args) 163 { 164 return ((isdigit(c) || (c == '-') || (c == '+')) ? TRUE : FALSE); 165 } 166 167 static FIELDTYPE builtin_integer = { 168 _TYPE_HAS_ARGS | _TYPE_IS_BUILTIN, /* flags */ 169 0, /* refcount */ 170 NULL, /* link */ 171 create_integer_args, /* make_args */ 172 copy_integer_args, /* copy_args */ 173 free_integer_args, /* free_args */ 174 integer_check_field, /* field_check */ 175 integer_check_char, /* char_check */ 176 NULL, /* next_choice */ 177 NULL /* prev_choice */ 178 }; 179 180 FIELDTYPE *TYPE_INTEGER = &builtin_integer; 181 182 183