6 #include <libsa/vers_rsrc.h>
7 #endif /* not KERNEL */
12 #define PRIV_EXT __private_extern__
13 #endif /* not KERNEL */
15 #define VERS_MAJOR_DIGITS (4)
16 #define VERS_MINOR_DIGITS (2)
17 #define VERS_REVISION_DIGITS (2)
18 #define VERS_STAGE_DIGITS (1)
19 #define VERS_STAGE_LEVEL_DIGITS (3)
21 #define VERS_MAJOR_MULT (100000000)
22 #define VERS_MINOR_MULT (1000000)
23 #define VERS_REVISION_MULT (10000)
24 #define VERS_STAGE_MULT (1000)
36 static int __vers_isdigit(char c
) {
38 c
== '1' || c
== '2' || c
== '3' ||
39 c
== '4' || c
== '5' || c
== '6' ||
40 c
== '7' || c
== '8' || c
== '9');
43 static int __vers_isspace(char c
) {
50 static int __vers_digit_for_char(char c
) {
52 case '0': return 0; break;
53 case '1': return 1; break;
54 case '2': return 2; break;
55 case '3': return 3; break;
56 case '4': return 4; break;
57 case '5': return 5; break;
58 case '6': return 6; break;
59 case '7': return 7; break;
60 case '8': return 8; break;
61 case '9': return 9; break;
62 default: return -1; break;
68 static int __VERS_isreleasestate(char c
) {
69 return (c
== 'd' || c
== 'a' || c
== 'b' || c
== 'f');
73 static VERS_stage
__VERS_stage_for_string(char ** string_p
) {
76 if (!string_p
|| !*string_p
) {
82 if (__vers_isspace(string
[0]) || string
[0] == '\0') {
87 if (__vers_isdigit(string
[1])) {
88 *string_p
= &string
[1];
89 return VERS_development
;
93 if (__vers_isdigit(string
[1])) {
94 *string_p
= &string
[1];
99 if (__vers_isdigit(string
[1])) {
100 *string_p
= &string
[1];
105 if (__vers_isdigit(string
[1])) {
106 *string_p
= &string
[1];
107 return VERS_candidate
;
108 } else if (string
[1] == 'c' && __vers_isdigit(string
[2])) {
109 *string_p
= &string
[2];
110 return VERS_candidate
;
124 static char * __VERS_string_for_stage(VERS_stage stage
) {
126 case VERS_invalid
: return "?"; break;
127 case VERS_development
: return "d"; break;
128 case VERS_alpha
: return "a"; break;
129 case VERS_beta
: return "b"; break;
130 case VERS_candidate
: return "f"; break;
131 case VERS_release
: return ""; break;
138 VERS_version
VERS_parse_string(const char * vers_string
) {
139 VERS_version result
= -1;
141 int num_digits_scanned
= 0;
142 VERS_version vers_major
= 0;
143 VERS_version vers_minor
= 0;
144 VERS_version vers_revision
= 0;
145 VERS_version vers_stage
= 0;
146 VERS_version vers_stage_level
= 0;
147 char * current_char_p
;
149 if (!vers_string
|| *vers_string
== '\0') {
153 current_char_p
= (char *)&vers_string
[0];
156 * Check for an initial digit of the major release number.
158 vers_major
= __vers_digit_for_char(*current_char_p
);
159 if (vers_major
< 0) {
164 num_digits_scanned
= 1;
166 /* Complete scan for major version number. Legal characters are
167 * any digit, period, any buildstage letter.
169 while (num_digits_scanned
< VERS_MAJOR_DIGITS
) {
170 if (__vers_isspace(*current_char_p
) || *current_char_p
== '\0') {
171 vers_stage
= VERS_release
;
173 } else if (__vers_isdigit(*current_char_p
)) {
174 vers_digit
= __vers_digit_for_char(*current_char_p
);
175 if (vers_digit
< 0) {
178 vers_major
= (vers_major
) * 10 + vers_digit
;
180 num_digits_scanned
++;
181 } else if (__VERS_isreleasestate(*current_char_p
)) {
183 } else if (*current_char_p
== '.') {
191 /* Check for too many digits.
193 if (num_digits_scanned
== VERS_MAJOR_DIGITS
) {
194 if (*current_char_p
== '.') {
196 } else if (__vers_isdigit(*current_char_p
)) {
203 num_digits_scanned
= 0;
205 /* Scan for minor version number. Legal characters are
206 * any digit, period, any buildstage letter.
208 while (num_digits_scanned
< VERS_MINOR_DIGITS
) {
209 if (__vers_isspace(*current_char_p
) || *current_char_p
== '\0') {
210 vers_stage
= VERS_release
;
212 } else if (__vers_isdigit(*current_char_p
)) {
213 vers_digit
= __vers_digit_for_char(*current_char_p
);
214 if (vers_digit
< 0) {
217 vers_minor
= (vers_minor
) * 10 + vers_digit
;
219 num_digits_scanned
++;
220 } else if (__VERS_isreleasestate(*current_char_p
)) {
222 } else if (*current_char_p
== '.') {
230 /* Check for too many digits.
232 if (num_digits_scanned
== VERS_MINOR_DIGITS
) {
233 if (*current_char_p
== '.') {
235 } else if (__vers_isdigit(*current_char_p
)) {
242 num_digits_scanned
= 0;
244 /* Scan for revision version number. Legal characters are
245 * any digit, any buildstage letter (NOT PERIOD).
247 while (num_digits_scanned
< VERS_REVISION_DIGITS
) {
248 if (__vers_isspace(*current_char_p
) || *current_char_p
== '\0') {
249 vers_stage
= VERS_release
;
251 } else if (__vers_isdigit(*current_char_p
)) {
252 vers_digit
= __vers_digit_for_char(*current_char_p
);
253 if (vers_digit
< 0) {
256 vers_revision
= (vers_revision
) * 10 + vers_digit
;
258 num_digits_scanned
++;
259 } else if (__VERS_isreleasestate(*current_char_p
)) {
266 /* Check for too many digits.
268 if (num_digits_scanned
== VERS_REVISION_DIGITS
) {
269 if (*current_char_p
== '.') {
271 } else if (__vers_isdigit(*current_char_p
)) {
279 * Check for the release state.
281 if (__vers_isspace(*current_char_p
) || *current_char_p
== '\0') {
282 vers_stage
= VERS_release
;
285 vers_stage
= __VERS_stage_for_string(¤t_char_p
);
286 if (vers_stage
== VERS_invalid
) {
294 num_digits_scanned
= 0;
296 /* Scan for stage level number. Legal characters are
299 while (num_digits_scanned
< VERS_STAGE_LEVEL_DIGITS
) {
300 if (__vers_isspace(*current_char_p
) || *current_char_p
== '\0') {
301 if (num_digits_scanned
) {
306 } else if (__vers_isdigit(*current_char_p
)) {
307 vers_digit
= __vers_digit_for_char(*current_char_p
);
308 if (vers_digit
< 0) {
311 vers_stage_level
= (vers_stage_level
) * 10 + vers_digit
;
313 num_digits_scanned
++;
319 /* Check for too many digits.
321 if ((num_digits_scanned
== VERS_STAGE_LEVEL_DIGITS
) &&
322 ! (__vers_isspace(*current_char_p
) || (*current_char_p
== '\0'))) {
327 if (vers_stage_level
> 255) {
333 if (vers_stage
== VERS_candidate
&& vers_stage_level
== 0) {
337 result
= (vers_major
* VERS_MAJOR_MULT
) +
338 (vers_minor
* VERS_MINOR_MULT
) +
339 (vers_revision
* VERS_REVISION_MULT
) +
340 (vers_stage
* VERS_STAGE_MULT
) +
346 #define VERS_STRING_MAX_LEN (16)
349 int VERS_string(char * buffer
, UInt32 length
, VERS_version vers
) {
351 VERS_version vers_major
= 0;
352 VERS_version vers_minor
= 0;
353 VERS_version vers_revision
= 0;
354 VERS_version vers_stage
= 0;
355 VERS_version vers_stage_level
= 0;
356 char * stage_string
= NULL
; // don't free
358 /* No buffer or length less than longest possible vers string,
361 if (!buffer
|| length
< VERS_STRING_MAX_LEN
) {
365 bzero(buffer
, length
* sizeof(char));
368 strcpy(buffer
, "(invalid)");
372 vers_major
= vers
/ VERS_MAJOR_MULT
;
374 vers_minor
= vers
- (vers_major
* VERS_MAJOR_MULT
);
375 vers_minor
/= VERS_MINOR_MULT
;
377 vers_revision
= vers
-
378 ( (vers_major
* VERS_MAJOR_MULT
) + (vers_minor
* VERS_MINOR_MULT
) );
379 vers_revision
/= VERS_REVISION_MULT
;
382 ( (vers_major
* VERS_MAJOR_MULT
) + (vers_minor
* VERS_MINOR_MULT
) +
383 (vers_revision
* VERS_REVISION_MULT
));
384 vers_stage
/= VERS_STAGE_MULT
;
386 vers_stage_level
= vers
-
387 ( (vers_major
* VERS_MAJOR_MULT
) + (vers_minor
* VERS_MINOR_MULT
) +
388 (vers_revision
* VERS_REVISION_MULT
) + (vers_stage
* VERS_STAGE_MULT
));
390 cpos
= sprintf(buffer
, "%lu", (UInt32
)vers_major
);
392 /* Always include the minor version; it just looks weird without.
396 cpos
+= sprintf(buffer
+cpos
, "%lu", (UInt32
)vers_minor
);
398 /* The revision is displayed only if nonzero.
403 cpos
+= sprintf(buffer
+cpos
, "%lu", (UInt32
)vers_revision
);
406 stage_string
= __VERS_string_for_stage(vers_stage
);
407 if (stage_string
&& stage_string
[0]) {
408 strcat(buffer
, stage_string
);
409 cpos
+= strlen(stage_string
);
412 if (vers_stage
< VERS_release
) {
413 sprintf(buffer
+cpos
, "%lu", (UInt32
)vers_stage_level
);