Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / bin / setversion.cpp
blobab9aa60789c0b10a5185fb54eceb2d0c0eb09e9c
1 /*
2 * Copyright 2002, Ryan Fleet.
3 * Copyright 2006-2007, Axel Dörfler, axeld@pinc-software.de.
5 * Distributed under the terms of the MIT license.
6 */
9 #include <AppFileInfo.h>
10 #include <String.h>
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
18 #ifdef HAIKU_HOST_PLATFORM_SUNOS
19 const char *kProgramName = "setversion";
20 #else
21 extern const char *__progname;
23 const char *kProgramName = __progname;
24 #endif
27 enum arg_needed {
28 switch_needed, major_version, middle_version, minor_version,
29 variety_version, internal_version, long_string, short_string
32 enum app_error {
33 e_base = B_ERRORS_END,
34 e_unknown, e_app_sys_switch, e_specify_version, e_major_version,
35 e_middle_version, e_minor_version, e_variety_version, e_internal_version,
36 e_expecting, e_long_string, e_short_string,
37 e_parameter, e_app_twice, e_sys_twice
40 enum processing_mode { no_switch, app_switch, sys_switch };
43 static void
44 usage()
46 fprintf(stdout, "Usage: %s filename\n", kProgramName);
47 fprintf(stdout, " [ -system <major> <middle> <minor>\n");
48 fprintf(stdout, " [ [ d | a | b | g | gm | f ] [ <internal> ] ]\n");
49 fprintf(stdout, " [ -short <shortVersionString> ]\n");
50 fprintf(stdout, " [ -long <longVersionString> ] ] # system info\n");
51 fprintf(stdout, " [ -app <major> <middle> <minor>\n");
52 fprintf(stdout, " [ [ d | a | b | g | gm | f ] [ <internal> ] ]\n");
53 fprintf(stdout, " [ -short <shortVersionString> ]\n");
54 fprintf(stdout, " [ -long <longVersionString> ] ] # application info\n");
58 static int
59 convertVariety(const char *str)
61 if (!strcmp(str, "d") || !strcmp(str, "development"))
62 return 0;
63 if (!strcmp(str, "a") || !strcmp(str, "alpha"))
64 return 1;
65 if (!strcmp(str, "b") || !strcmp(str, "beta"))
66 return 2;
67 if (!strcmp(str, "g") || !strcmp(str, "gamma"))
68 return 3;
69 if (strcmp(str, "gm") || !strcmp(str, "goldenmaster"))
70 return 4;
71 if (!strcmp(str, "f") || !strcmp(str, "final"))
72 return 5;
74 return -1;
78 static void
79 errorToString(BString& output, status_t error, const char *appName = NULL)
81 switch (error) {
82 case e_app_sys_switch:
83 output = "-system or -app expected\n";
84 break;
85 case e_specify_version:
86 output = "you did not specify any version\n";
87 break;
88 case e_major_version:
89 output = "major version number error\n";
90 break;
91 case e_middle_version:
92 output = "middle version number error\n";
93 break;
94 case e_minor_version:
95 output = "minor version number error\n";
96 break;
97 case e_variety_version:
98 output = "variety letter error\n";
99 break;
100 case e_internal_version:
101 output = "internal version number error\n";
102 break;
103 case e_expecting:
104 output = "expecting -short, -long, -app or -system\n";
105 break;
106 case e_long_string:
107 output = "expecting long version string\n";
108 break;
109 case e_short_string:
110 output = "expecting short version string\n";
111 break;
112 case e_parameter:
113 output = "parameter error\n";
114 break;
115 case e_app_twice:
116 output = "you cannot specify the app version twice\n";
117 break;
118 case e_sys_twice:
119 output = "you cannot specify the system version twice\n";
120 break;
121 case e_unknown:
122 output = "unknown internal error\n";
123 break;
125 default:
126 output = strerror(error);
128 if (appName != NULL) {
129 output += ": ";
130 output += appName;
132 break;
137 static int
138 errorOut(status_t error, const char *appName = NULL, bool showUsage = true)
140 BString output;
141 errorToString(output, error, appName);
143 fprintf(stderr, "%s: %s", kProgramName, output.String());
145 if (showUsage)
146 usage();
148 exit(1);
152 static void
153 parse(bool &systemModified, bool &appModified, arg_needed &argNeeded,
154 processing_mode &mode, version_info &systemVersion, version_info &appVersion,
155 int argc, char *argv[])
157 systemModified = false;
158 appModified = false;
159 mode = no_switch;
160 argNeeded = switch_needed;
162 for (int i = 2; i < argc; ++i) {
163 version_info &version = mode == app_switch ? appVersion : systemVersion;
165 switch (argNeeded) {
166 case switch_needed:
167 if (strcmp(argv[i], "-app") == 0) {
168 if (mode == app_switch)
169 errorOut(e_app_twice);
170 if (appModified)
171 errorOut(e_parameter);
173 mode = app_switch;
174 argNeeded = major_version;
175 appModified = true;
176 } else if (strcmp(argv[i], "-system") == 0) {
177 if (mode == sys_switch)
178 errorOut(e_sys_twice);
179 if (systemModified)
180 errorOut(e_parameter);
182 mode = sys_switch;
183 argNeeded = major_version;
184 systemModified = true;
185 } else if (strcmp(argv[i], "-long") == 0) {
186 if (mode == no_switch)
187 errorOut(e_app_sys_switch);
189 argNeeded = long_string;
190 } else if (strcmp(argv[i], "-short") == 0) {
191 if (mode == no_switch)
192 errorOut(e_app_sys_switch);
194 argNeeded = short_string;
195 } else if (mode == no_switch)
196 errorOut(e_app_sys_switch);
197 else if (strncmp(argv[i], "-", 1) == 0)
198 errorOut(e_parameter);
199 else
200 errorOut(e_expecting);
201 break;
203 case major_version:
204 if (isalpha(argv[i][0]))
205 errorOut(e_major_version);
207 version.major = atoi(argv[i]);
208 argNeeded = middle_version;
209 break;
211 case middle_version:
212 if (isalpha(argv[i][0]))
213 errorOut(e_middle_version);
215 version.middle = atoi(argv[i]);
216 argNeeded = minor_version;
217 break;
219 case minor_version:
220 if (isalpha(argv[i][0]))
221 errorOut(e_minor_version);
223 version.minor = atoi(argv[i]);
225 if (i >= argc-1) {
226 argNeeded = switch_needed;
227 break;
230 argNeeded = variety_version;
231 break;
233 case variety_version:
235 if (!strncmp(argv[i], "-", 1)) {
236 i--;
237 argNeeded = switch_needed;
238 break;
241 int variety = convertVariety(argv[i]);
242 if (variety < 0)
243 errorOut(e_variety_version);
245 version.variety = variety;
246 argNeeded = internal_version;
247 break;
250 case internal_version:
251 if (isalpha(argv[i][0]))
252 errorOut(e_expecting);
254 version.internal = atoi(argv[i]);
255 argNeeded = switch_needed;
256 break;
258 case long_string:
259 strcpy(version.long_info, argv[i]);
260 argNeeded = switch_needed;
261 break;
263 case short_string:
264 strcpy(version.short_info, argv[i]);
265 argNeeded = switch_needed;
266 break;
270 if (mode == no_switch)
271 errorOut(e_app_sys_switch);
273 switch (argNeeded) {
274 case major_version:
275 errorOut(e_major_version);
276 break;
277 case middle_version:
278 errorOut(e_middle_version);
279 break;
280 case minor_version:
281 errorOut(e_minor_version);
282 break;
283 case variety_version:
284 errorOut(e_variety_version);
285 break;
286 case internal_version:
287 errorOut(e_internal_version);
288 break;
289 case long_string:
290 errorOut(e_long_string);
291 break;
292 case short_string:
293 errorOut(e_short_string);
294 break;
295 case switch_needed:
296 // all is well
297 break;
303 main(int argc, char *argv[])
305 if (argc < 3) {
306 if (argc < 2)
307 return errorOut(e_app_sys_switch);
309 return errorOut(e_specify_version);
312 // reset version infos
314 version_info systemVersion, appVersion;
315 memset(&systemVersion, 0, sizeof(version_info));
316 memset(&appVersion, 0, sizeof(version_info));
318 // process arguments
320 processing_mode mode;
321 arg_needed argNeeded;
322 bool systemModified, appModified;
324 parse(systemModified, appModified, argNeeded, mode, systemVersion,
325 appVersion, argc, argv);
327 // write back changes
329 BFile file;
330 status_t status = file.SetTo(argv[1], B_READ_WRITE);
331 if (status != B_OK)
332 errorOut(status, argv[1], false);
334 BAppFileInfo info;
335 status = info.SetTo(&file);
336 if (status != B_OK)
337 errorOut(status, argv[1], false);
339 if (systemModified ^ appModified) {
340 // clear out other app info if not present - this works around a
341 // bug in BeOS, see bug #681.
342 version_kind kind = systemModified ? B_APP_VERSION_KIND : B_SYSTEM_VERSION_KIND;
343 version_info clean;
345 if (info.GetVersionInfo(&clean, kind) != B_OK) {
346 memset(&clean, 0, sizeof(version_info));
347 info.SetVersionInfo(&clean, kind);
351 if (appModified) {
352 status = info.SetVersionInfo(&appVersion, B_APP_VERSION_KIND);
353 if (status < B_OK)
354 errorOut(status, NULL, false);
357 if (systemModified) {
358 status = info.SetVersionInfo(&systemVersion, B_SYSTEM_VERSION_KIND);
359 if (status < B_OK)
360 errorOut(status, NULL, false);
363 return 0;