2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
19 FLAG_MANDATORY_FIELD
= 0x01,
20 FLAG_LIST_ATTRIBUTE
= 0x02,
21 FLAG_DONT_QUOTE
= 0x04,
25 extern const char* __progname
;
26 const char* kCommandName
= __progname
;
29 static const char* kUsage
=
30 "Usage: %s [ <options> ] <optional package description> "
31 "[ <package info> ]\n"
32 "Converts an .OptionalPackageDescription to a .PackageInfo. If "
34 "is not specified, the output is printed to stdout.\n"
35 "Note that the generated .PackageInfo will not be complete. For several\n"
36 "fields an empty string will be used, unless specified via an option.\n"
37 "The \"provides\" and \"requires\" lists will always be empty, though\n"
40 " -a <arch> - Use the given architecture string. Default is to "
41 "guess from the file name.\n"
42 " -d <description> - Use the given descripton string. Default is to use\n"
44 " -h, --help - Print this usage info.\n"
45 " -p <packager> - Use the given packager string. Default is an empty "
47 " -s <summary> - Use the given summary string. Default is an empty "
49 " -v <version> - Use the given version string. Overrides the version\n"
50 " from the input file.\n"
51 " -V <vendor> - Use the given vendor string. Default is an empty "
57 print_usage_and_exit(bool error
)
59 fprintf(error
? stderr
: stdout
, kUsage
, kCommandName
);
65 guess_architecture(const char* name
)
67 if (strstr(name
, "x86") != NULL
) {
68 if (strstr(name
, "gcc4") != NULL
)
79 OuputWriter(FILE* output
, const BMessage
& package
)
86 void WriteAttribute(const char* attributeName
, const char* fieldName
,
87 const char* defaultValue
, uint32 flags
)
89 if (fieldName
!= NULL
) {
92 if (fPackage
.GetInfo(fieldName
, &type
, &count
) != B_OK
) {
93 if ((flags
& FLAG_MANDATORY_FIELD
) != 0) {
94 fprintf(stderr
, "Error: Missing mandatory field \"%s\" in "
95 "input file.\n", fieldName
);
104 fPackage
.FindString(fieldName
, &value
);
105 _WriteSingleElementAttribute(attributeName
, value
, flags
);
107 fprintf(fOutput
, "\n%s {\n", attributeName
);
109 for (int32 i
= 0; i
< count
; i
++) {
110 fprintf(fOutput
, "\t");
112 fPackage
.FindString(fieldName
, i
, &value
);
113 _WriteValue(value
, flags
);
114 fputc('\n', fOutput
);
117 fputs("}\n", fOutput
);
124 // write the default value
125 if (defaultValue
!= NULL
)
126 _WriteSingleElementAttribute(attributeName
, defaultValue
, flags
);
130 void _WriteSingleElementAttribute(const char* attributeName
,
131 const char* value
, uint32 flags
)
133 fputs(attributeName
, fOutput
);
135 int32 indentation
= 16 - (int32
)strlen(attributeName
);
137 indentation
= (indentation
+ 3) / 4;
141 for (int32 i
= 0; i
< indentation
; i
++)
142 fputc('\t', fOutput
);
144 _WriteValue(value
, flags
);
145 fputc('\n', fOutput
);
148 void _WriteValue(const char* value
, uint32 flags
)
150 BString
escapedValue(value
);
152 if ((flags
& FLAG_DONT_QUOTE
) != 0) {
153 escapedValue
.CharacterEscape("\\\"' \t", '\\');
154 fputs(escapedValue
.String(), fOutput
);
156 escapedValue
.CharacterEscape("\\\"", '\\');
157 fprintf(fOutput
, "\"%s\"", escapedValue
.String());
163 const BMessage
& fPackage
;
168 main(int argc
, const char* const* argv
)
170 const char* architecture
= NULL
;
171 const char* version
= NULL
;
172 const char* summary
= "";
173 const char* description
= "";
174 const char* packager
= "";
175 const char* vendor
= "";
178 static const struct option kLongOptions
[] = {
179 { "help", no_argument
, 0, 'h' },
183 opterr
= 0; // don't print errors
184 int c
= getopt_long(argc
, (char**)argv
, "+ha:d:p:s:v:V:", kLongOptions
,
191 architecture
= optarg
;
195 description
= optarg
;
199 print_usage_and_exit(false);
219 print_usage_and_exit(true);
224 // One or two argument should remain -- the input file and optionally the
226 if (optind
+ 1 != argc
&& optind
+ 2 != argc
)
227 print_usage_and_exit(true);
229 const char* opdName
= argv
[optind
++];
230 const char* packageInfoName
= optind
< argc
? argv
[optind
++] : NULL
;
232 // guess architecture from the input file name, if not given
233 if (architecture
== NULL
) {
234 const char* fileName
= strrchr(opdName
, '/');
235 if (fileName
== NULL
)
240 // Try to guess from the file name.
241 architecture
= guess_architecture(fileName
);
243 // If we've got nothing yet, try to guess from the file name.
244 if (architecture
== NULL
&& fileName
!= opdName
)
245 architecture
= guess_architecture(opdName
);
248 if (architecture
== NULL
)
249 architecture
= "any";
253 FILE* input
= fopen(opdName
, "r");
255 fprintf(stderr
, "Failed to open input file \"%s\": %s\n", opdName
,
261 FILE* output
= packageInfoName
!= NULL
262 ? fopen(packageInfoName
, "w+") : stdout
;
263 if (output
== NULL
) {
264 fprintf(stderr
, "Failed to open output file \"%s\": %s\n",
265 packageInfoName
, strerror(errno
));
269 // read and parse the input file
273 char lineBuffer
[LINE_MAX
];
274 bool seenPackageAttribute
= false;
276 while (char* line
= fgets(lineBuffer
, sizeof(lineBuffer
), input
)) {
277 // chop off line break
278 size_t lineLen
= strlen(line
);
279 if (lineLen
> 0 && line
[lineLen
- 1] == '\n')
280 line
[--lineLen
] = '\0';
282 // flush previous field, if a new field begins, otherwise append
283 if (lineLen
== 0 || !isspace(line
[0])) {
284 // new field -- flush the previous one
285 if (fieldName
.Length() > 0) {
287 package
.AddString(fieldName
.String(), fieldValue
);
290 } else if (fieldName
.Length() > 0) {
291 // append to current field
295 // bogus line -- ignore
303 char* colon
= strchr(line
, ':');
305 // bogus line -- ignore
309 fieldName
.SetTo(line
, colon
- line
);
311 if (fieldName
.Length() == 0) {
312 // invalid field name
316 fieldValue
= colon
+ 1;
318 if (fieldName
== "Package") {
319 if (seenPackageAttribute
) {
320 fprintf(stderr
, "Duplicate \"Package\" attribute!\n");
324 seenPackageAttribute
= true;
329 OuputWriter
writer(output
, package
);
332 writer
.WriteAttribute("name", "Package", NULL
,
333 FLAG_MANDATORY_FIELD
| FLAG_DONT_QUOTE
);
336 writer
.WriteAttribute("version", "Version", version
, FLAG_DONT_QUOTE
);
339 fprintf(output
, "architecture\t%s\n", architecture
);
342 fprintf(output
, "summary\t\t\t\"%s\"\n", summary
);
345 if (description
!= NULL
)
346 fprintf(output
, "description\t\t\"%s\"\n", description
);
348 fprintf(output
, "description\t\t\"%s\"\n", summary
);
351 fprintf(output
, "packager\t\t\"%s\"\n", packager
);
354 fprintf(output
, "vendor\t\t\t\"%s\"\n", vendor
);
357 writer
.WriteAttribute("copyrights", "Copyright", NULL
,
358 FLAG_MANDATORY_FIELD
| FLAG_LIST_ATTRIBUTE
);
361 writer
.WriteAttribute("licenses", "License", NULL
, FLAG_LIST_ATTRIBUTE
);
364 fprintf(output
, "\nprovides {\n}\n");
367 fprintf(output
, "\nrequires {\n}\n");
370 writer
.WriteAttribute("urls", "URL", NULL
, FLAG_LIST_ATTRIBUTE
);
373 writer
.WriteAttribute("source-urls", "SourceURL", NULL
,
374 FLAG_LIST_ATTRIBUTE
);