1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#include <stdlib.h>
24#include <string.h>
25
26#include "stuff/bool.h"
27#include "stuff/allocate.h"
28#include "stuff/errors.h"
29
30/*
31 * get_version_number() converts an ascii version number string of the form:
32 *	X[.Y[.Z]]
33 * to a uint32_t with the value (X << 16) | (Y << 8) | Z and does
34 * all the needed range checks.  The value is indirectly returned through value
35 * and flag and argument are used for error messages.  It TRUE if there were
36 * no errors FALSE otherwise.
37 */
38__private_extern__
39enum bool
40get_version_number(
41char *flag,
42char *argument,
43uint32_t *value)
44{
45    char *p, *x, *y, *z, *dot, *endp;
46    uint32_t X, Y, Z;
47
48	*value = 0;
49	p = allocate(strlen(argument) + 1);
50	strcpy(p, argument);
51
52	y = NULL;
53	z = NULL;
54
55	x = p;
56	dot = strchr(x, '.');
57	if(dot != NULL && dot[1] != '\0'){
58	    *dot = '\0';
59	    y = dot + 1;
60	    dot = strchr(y, '.');
61	    if(dot != NULL && dot[1] != '\0'){
62		*dot = '\0';
63		z = dot + 1;
64		dot = strchr(z, '.');
65		if(dot != NULL){
66		    *dot = '\0';
67		}
68	    }
69	}
70
71	Y = 0;
72	Z = 0;
73
74	X = strtoul(x, &endp, 10);
75	if(*endp != '\0'){
76	    error("first field (%s) in argument for: %s %s not a proper "
77		  "unsigned number", x, flag, argument);
78	    goto fail;
79	}
80	if(X > 0xffff){
81	    error("first field (%s) in argument for: %s %s too large (maximum "
82		  "%d)", x, flag, argument, 0xffff);
83	    goto fail;
84	}
85	if(y != NULL){
86	    Y = strtoul(y, &endp, 10);
87	    if(*endp != '\0'){
88		error("second field (%s) in argument for: %s %s not a proper "
89		      "unsigned number", y, flag, argument);
90		goto fail;
91	    }
92	    if(Y > 0xff){
93		error("second field (%s) in argument for: %s %s too large "
94		      "(maximum %d)", y, flag, argument, 0xff);
95		goto fail;
96	    }
97	    if(z != NULL){
98		Z = strtoul(z, &endp, 10);
99		if(*endp != '\0'){
100		    error("third field (%s) in argument for: %s %s not a "
101			  "proper unsigned number", z, flag, argument);
102		    goto fail;
103		}
104		if(Z > 0xff){
105		    error("third field (%s) in argument for: %s %s too large "
106			  "(maximum %d)", z, flag, argument, 0xff);
107		    goto fail;
108		}
109	    }
110	}
111	*value = (X << 16) | (Y << 8) | Z;
112	free(p);
113	return((enum bool)TRUE);
114
115fail:
116	free(p);
117	return((enum bool)FALSE);
118}
119