* Did not initialize the version info, so if they were only partially changed,

it would leave some junk in there.
* No more usage info on file errors.
* Simplified and improved error handling quite a bit (better and more correct
  error messages in case of file errors).
* Cleaned up a lot, it now fits our coding style guide.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17827 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-06-13 17:21:44 +00:00
parent 85376415a4
commit 8eff00736e

View File

@ -1,35 +1,45 @@
// Author: Ryan Fleet /*
// Created: 12th October 2002 * Copyright 2002, Ryan Fleet.
// Modified: 14th October 2002 * Copyright 2006, Axel Dörfler, axeld@pinc-software.de.
*
* Distributed under the terms of the MIT license.
*/
#include <AppFileInfo.h>
#include <String.h>
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include <AppFileInfo.h>
enum eArgNeeded extern const char *__progname;
{
const char *kProgramName = __progname;
enum arg_needed {
switch_needed, major_version, middle_version, minor_version, switch_needed, major_version, middle_version, minor_version,
variety_version, internal_version, long_string, short_string variety_version, internal_version, long_string, short_string
}; };
enum eError enum app_error {
{ e_base = B_ERRORS_END,
e_unknown, e_app_sys_switch, e_specify_version, e_major_version, e_unknown, e_app_sys_switch, e_specify_version, e_major_version,
e_middle_version, e_minor_version, e_variety_version, e_internal_version, e_middle_version, e_minor_version, e_variety_version, e_internal_version,
e_expecting, e_long_string, e_short_string, e_no_file, e_expecting, e_long_string, e_short_string,
e_parameter, e_app_twice, e_sys_twice e_parameter, e_app_twice, e_sys_twice
}; };
enum eMode { no_switch, app_switch, sys_switch }; enum processing_mode { no_switch, app_switch, sys_switch };
void usage(const char *app) static void
usage()
{ {
fprintf(stdout, "Usage: %s filename\n", app); fprintf(stdout, "Usage: %s filename\n", kProgramName);
fprintf(stdout, " [ -system <major> <middle> <minor>\n"); fprintf(stdout, " [ -system <major> <middle> <minor>\n");
fprintf(stdout, " [ [ d | a | b | g | gm | f ] [ <internal> ] ]\n"); fprintf(stdout, " [ [ d | a | b | g | gm | f ] [ <internal> ] ]\n");
fprintf(stdout, " [ -short <shortVersionString> ]\n"); fprintf(stdout, " [ -short <shortVersionString> ]\n");
@ -41,348 +51,299 @@ void usage(const char *app)
} }
int convertVariety(const char *str) static int
convertVariety(const char *str)
{ {
if(strcmp(str, "d") == 0) if (!strcmp(str, "d") || !strcmp(str, "development"))
return 0; return 0;
else if(strcmp(str, "a") == 0) if (!strcmp(str, "a") || !strcmp(str, "alpha"))
return 1; return 1;
else if(strcmp(str, "b") == 0) if (!strcmp(str, "b") || !strcmp(str, "beta"))
return 2; return 2;
else if(strcmp(str, "g") == 0) if (!strcmp(str, "g") || !strcmp(str, "gamma"))
return 3; return 3;
else if(strcmp(str, "gm") == 0) if (strcmp(str, "gm") || !strcmp(str, "goldenmaster"))
return 4; return 4;
else if(strcmp(str, "f") == 0) if (!strcmp(str, "f") || !strcmp(str, "final"))
return 5; return 5;
else
return -1; return -1;
} }
int errorOut(eError error, const char *thisApp, const char *appName = NULL) static void
errorToString(BString& output, status_t error, const char *appName = NULL)
{ {
switch(error) switch (error) {
{ case e_app_sys_switch:
case e_app_sys_switch: output = "-system or -app expected\n";
fprintf(stderr, "%s: -system or -app expected\n", thisApp); break;
break; case e_specify_version:
case e_specify_version: output = "you did not specify any version\n";
fprintf(stderr, "%s: you did not specify any version\n", thisApp); break;
break; case e_major_version:
case e_major_version: output = "major version number error\n";
fprintf(stderr, "%s: major version number error\n", thisApp); break;
break; case e_middle_version:
case e_middle_version: output = "middle version number error\n";
fprintf(stderr, "%s: middle version number error\n", thisApp); break;
break; case e_minor_version:
case e_minor_version: output = "minor version number error\n";
fprintf(stderr, "%s: minor version number error\n", thisApp); break;
break; case e_variety_version:
case e_variety_version: output = "variety letter error\n";
fprintf(stderr, "%s: variety letter error\n", thisApp); break;
break; case e_internal_version:
case e_internal_version: output = "internal version number error\n";
fprintf(stderr, "%s: internal version number error\n", thisApp); break;
break; case e_expecting:
case e_expecting: output = "expecting -short, -long, -app or -system\n";
fprintf(stderr, "%s: expecting -short, -long, -app or -system\n", thisApp); break;
break; case e_long_string:
case e_long_string: output = "expecting long version string\n";
fprintf(stderr, "%s: expecting long version string\n", thisApp); break;
break; case e_short_string:
case e_short_string: output = "expecting short version string\n";
fprintf(stderr, "%s: expecting short version string\n", thisApp); break;
break; case e_parameter:
case e_no_file: output = "parameter error\n";
fprintf(stderr, "%s: error No such file or directory opening file %s!\n", thisApp, appName); break;
break; case e_app_twice:
case e_parameter: output = "you cannot specify the app version twice\n";
fprintf(stderr, "%s: parameter error\n", thisApp); break;
break; case e_sys_twice:
case e_app_twice: output = "you cannot specify the system version twice\n";
fprintf(stderr, "%s: you cannot specify the app version twice\n", thisApp); break;
break; case e_unknown:
case e_sys_twice: output = "unknown internal error\n";
fprintf(stderr, "%s: you cannot specify the system version twice\n", thisApp); break;
break;
case e_unknown: default:
fprintf(stderr, "%s: unknown internal error\n", thisApp); output = strerror(error);
break;
}; if (appName != NULL) {
output += ": ";
usage(thisApp); output += appName;
}
break;
}
}
static int
errorOut(status_t error, const char *appName = NULL, bool showUsage = true)
{
BString output;
errorToString(output, error, appName);
fprintf(stderr, "%s: %s", kProgramName, output.String());
if (showUsage)
usage();
exit(1); exit(1);
} }
void parse(bool &bSysModified, bool &bAppModified, eArgNeeded &argNeeded, eMode &mode, version_info &sysInfo, version_info &appInfo, int argc, char *argv[]) static void
parse(bool &systemModified, bool &appModified, arg_needed &argNeeded,
processing_mode &mode, version_info &systemVersion, version_info &appVersion,
int argc, char *argv[])
{ {
bSysModified = false; systemModified = false;
bAppModified = false; appModified = false;
mode = no_switch; mode = no_switch;
argNeeded = switch_needed; argNeeded = switch_needed;
for(int i = 2; i < argc; ++i) for (int i = 2; i < argc; ++i) {
{ version_info &version = mode == app_switch ? appVersion : systemVersion;
switch(argNeeded)
{ switch (argNeeded) {
case switch_needed: case switch_needed:
{ if (strcmp(argv[i], "-app") == 0) {
if(strcmp(argv[i], "-app") == 0) if (mode == app_switch)
{ errorOut(e_app_twice);
if(mode == app_switch) if (appModified)
errorOut(e_app_twice, argv[0]); errorOut(e_parameter);
if(true == bAppModified)
errorOut(e_parameter, argv[0]);
mode = app_switch; mode = app_switch;
argNeeded = major_version; argNeeded = major_version;
bAppModified = true; appModified = true;
} } else if (strcmp(argv[i], "-system") == 0) {
else if(strcmp(argv[i], "-system") == 0) if (mode == sys_switch)
{ errorOut(e_sys_twice);
if(mode == sys_switch) if (systemModified)
errorOut(e_sys_twice, argv[0]); errorOut(e_parameter);
if(true == bSysModified)
errorOut(e_parameter, argv[0]);
mode = sys_switch; mode = sys_switch;
argNeeded = major_version; argNeeded = major_version;
bSysModified = true; systemModified = true;
} } else if (strcmp(argv[i], "-long") == 0) {
else if(strcmp(argv[i], "-long") == 0) if (mode == no_switch)
{ errorOut(e_app_sys_switch);
if(mode == no_switch)
errorOut(e_app_sys_switch, argv[0]);
argNeeded = long_string; argNeeded = long_string;
} } else if (strcmp(argv[i], "-short") == 0) {
else if(strcmp(argv[i], "-short") == 0) if (mode == no_switch)
{ errorOut(e_app_sys_switch);
if(mode == no_switch)
errorOut(e_app_sys_switch, argv[0]);
argNeeded = short_string; argNeeded = short_string;
} } else if (mode == no_switch)
else if(mode == no_switch) errorOut(e_app_sys_switch);
errorOut(e_app_sys_switch, argv[0]); else if (strncmp(argv[i], "-", 1) == 0)
else if(strncmp(argv[i], "-", 1) == 0) errorOut(e_parameter);
errorOut(e_parameter, argv[0]);
else else
errorOut(e_expecting, argv[0]); errorOut(e_expecting);
} break; break;
case major_version: case major_version:
{ if (isalpha(argv[i][0]))
if(mode == app_switch) errorOut(e_major_version);
{
if(isalpha(argv[i][0])) version.major = atoi(argv[i]);
errorOut(e_major_version, argv[0]);
appInfo.major = atoi(argv[i]);
}
else if(mode == sys_switch)
{
if(isalpha(argv[i][0]))
errorOut(e_major_version, argv[0]);
sysInfo.major = atoi(argv[i]);
}
else
errorOut(e_unknown, argv[0]); // (should never reach here)
argNeeded = middle_version; argNeeded = middle_version;
} break; break;
case middle_version: case middle_version:
{ if (isalpha(argv[i][0]))
if(mode == app_switch) errorOut(e_middle_version);
{
if(isalpha(argv[i][0])) version.middle = atoi(argv[i]);
errorOut(e_middle_version, argv[0]);
appInfo.middle = atoi(argv[i]);
}
else if(mode == sys_switch)
{
if(isalpha(argv[i][0]))
errorOut(e_middle_version, argv[0]);
sysInfo.middle = atoi(argv[i]);
}
else
errorOut(e_unknown, argv[0]); // (should never reach here)
argNeeded = minor_version; argNeeded = minor_version;
} break; break;
case minor_version: case minor_version:
{ if (isalpha(argv[i][0]))
if(mode == app_switch) errorOut(e_minor_version);
{
if(isalpha(argv[i][0])) version.minor = atoi(argv[i]);
errorOut(e_minor_version, argv[0]);
if (i >= argc-1) {
appInfo.minor = atoi(argv[i]);
}
else if(mode == sys_switch)
{
if(isalpha(argv[i][0]))
errorOut(e_minor_version, argv[0]);
sysInfo.minor = atoi(argv[i]);
}
else
errorOut(e_unknown, argv[0]); // (should never reach here)
if(i >= argc-1)
{
argNeeded = switch_needed; argNeeded = switch_needed;
break; break;
} }
argNeeded = variety_version; argNeeded = variety_version;
} break; break;
case variety_version:
case variety_version:
{ {
if(strncmp(argv[i], "-", 1) == 0) if (!strncmp(argv[i], "-", 1)) {
{ i--;
--i;
argNeeded = switch_needed; argNeeded = switch_needed;
break; break;
} }
if(mode == app_switch) int variety = convertVariety(argv[i]);
{ if (variety < 0)
int v = convertVariety(argv[i]); errorOut(e_variety_version);
if(v < 0)
errorOut(e_variety_version, argv[0]); version.variety = variety;
appInfo.variety = v;
}
else if(mode == sys_switch)
{
int v = convertVariety(argv[i]);
if(v < 0)
errorOut(e_variety_version, argv[0]);
sysInfo.variety = v;
}
else
errorOut(e_unknown, argv[0]); // (should never reach here)
argNeeded = internal_version; argNeeded = internal_version;
} break; break;
case internal_version: }
{
if(mode == app_switch) case internal_version:
{ if (isalpha(argv[i][0]))
if(isalpha(argv[i][0])) errorOut(e_expecting);
errorOut(e_expecting, argv[0]);
version.internal = atoi(argv[i]);
appInfo.internal = atoi(argv[i]);
}
else if(mode == sys_switch)
{
if(isalpha(argv[i][0]))
errorOut(e_expecting, argv[0]);
sysInfo.internal = atoi(argv[i]);
}
else
errorOut(e_unknown, argv[0]); // (should never reach here)
argNeeded = switch_needed; argNeeded = switch_needed;
} break; break;
case long_string:
{ case long_string:
if(mode == app_switch) strcpy(version.long_info, argv[i]);
strcpy(appInfo.long_info, argv[i]);
else if(mode == sys_switch)
strcpy(sysInfo.long_info, argv[i]);
else
errorOut(e_unknown, argv[0]); // (should never reach here)
argNeeded = switch_needed; argNeeded = switch_needed;
} break; break;
case short_string:
{ case short_string:
if(mode == app_switch) strcpy(version.short_info, argv[i]);
strcpy(appInfo.short_info, argv[i]);
else if(mode == sys_switch)
strcpy(sysInfo.short_info, argv[i]);
else
errorOut(e_unknown, argv[0]); // (should never reach here)
argNeeded = switch_needed; argNeeded = switch_needed;
} break; break;
}; }
}
if (mode == no_switch)
errorOut(e_app_sys_switch);
switch (argNeeded) {
case major_version:
errorOut(e_major_version);
break;
case middle_version:
errorOut(e_middle_version);
break;
case minor_version:
errorOut(e_minor_version);
break;
case variety_version:
errorOut(e_variety_version);
break;
case internal_version:
errorOut(e_internal_version);
break;
case long_string:
errorOut(e_long_string);
break;
case short_string:
errorOut(e_short_string);
break;
case switch_needed:
// all is well
break;
} }
if(mode == no_switch)
errorOut(e_app_sys_switch, argv[0]);
switch(argNeeded)
{
case major_version:
errorOut(e_major_version, argv[0]);
break;
case middle_version:
errorOut(e_middle_version, argv[0]);
break;
case minor_version:
errorOut(e_minor_version, argv[0]);
break;
case variety_version:
errorOut(e_variety_version, argv[0]);
break;
case internal_version:
errorOut(e_internal_version, argv[0]);
break;
case long_string:
errorOut(e_long_string, argv[0]);
break;
case short_string:
errorOut(e_short_string, argv[0]);
break;
case switch_needed:
// all is well. continue
break;
};
} }
int main(int argc, char *argv[]) int
main(int argc, char *argv[])
{ {
if(argc < 3) if (argc < 3) {
{ if (argc < 2)
if(argc < 2) return errorOut(e_app_sys_switch);
return errorOut(e_app_sys_switch, argv[0]);
else
return errorOut(e_specify_version, argv[0]);
}
eMode mode;
eArgNeeded argNeeded;
version_info sysInfo, appInfo;
bool bSysModified, bAppModified;
parse(bSysModified, bAppModified, argNeeded, mode, sysInfo, appInfo, argc, argv); return errorOut(e_specify_version);
BFile file(argv[1], B_READ_WRITE);
if(file.InitCheck() != B_OK)
errorOut(e_no_file, argv[0], argv[1]);
BAppFileInfo info(&file);
if(info.InitCheck() != B_OK)
errorOut(e_unknown, argv[0]);
status_t status;
if(bAppModified)
{
status = info.SetVersionInfo(&appInfo, B_APP_VERSION_KIND);
if(status < 0)
errorOut(e_unknown, argv[0]);
} }
if(bSysModified) // reset version infos
{
status = info.SetVersionInfo(&sysInfo, B_SYSTEM_VERSION_KIND); version_info systemVersion, appVersion;
if(status < 0) memset(&systemVersion, 0, sizeof(version_info));
errorOut(e_unknown, argv[0]); memset(&appVersion, 0, sizeof(version_info));
// process arguments
processing_mode mode;
arg_needed argNeeded;
bool systemModified, appModified;
parse(systemModified, appModified, argNeeded, mode, systemVersion,
appVersion, argc, argv);
// write back changes
BFile file;
status_t status = file.SetTo(argv[1], B_READ_WRITE);
if (status != B_OK)
errorOut(status, argv[1], false);
BAppFileInfo info;
status = info.SetTo(&file);
if (status != B_OK)
errorOut(status, argv[1], false);
if (appModified) {
status = info.SetVersionInfo(&appVersion, B_APP_VERSION_KIND);
if (status < B_OK)
errorOut(status, NULL, false);
}
if (systemModified) {
status = info.SetVersionInfo(&systemVersion, B_SYSTEM_VERSION_KIND);
if (status < B_OK)
errorOut(status, NULL, false);
} }
return 0; return 0;
} }