blob: e386b429fe5ca5dd5e2bb6e38d9401a3c841d6f2 [file] [log] [blame]
scroggo@google.com161e1ba2013-03-04 16:41:06 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkFlags.h"
9
10SkFlagInfo* SkFlags::gHead;
11SkString SkFlags::gUsage;
12
13void SkFlags::SetUsage(const char* usage) {
14 gUsage.set(usage);
15}
16
17// Maximum line length for the help message.
18#define LINE_LENGTH 80
19
20void SkFlags::ParseCommandLine(int argc, char** argv) {
21 // Only allow calling this function once.
22 static bool gOnce;
23 if (gOnce) {
24 SkDebugf("ParseCommandLine should only be called once at the beginning"
25 " of main!\n");
26 SkASSERT(false);
27 return;
28 }
29 gOnce = true;
30
31 bool helpPrinted = false;
32 // Loop over argv, starting with 1, since the first is just the name of the program.
33 for (int i = 1; i < argc; i++) {
34 if (0 == strcmp("-h", argv[i]) || 0 == strcmp("--h", argv[i])
35 || 0 == strcmp("-help", argv[i]) || 0 == strcmp("--help", argv[i])) {
36 // Print help message.
37 SkDebugf("%s\n%s\n", argv[0], gUsage.c_str());
38 SkDebugf("Flags:\n");
39 SkFlagInfo* flag = SkFlags::gHead;
40 while (flag != NULL) {
scroggo@google.com09fd4d22013-03-20 14:20:18 +000041 SkDebugf("\t--%s:\ttype: %s", flag->name().c_str(),
42 flag->typeAsString().c_str());
43 if (flag->defaultValue().size() > 0) {
44 SkDebugf("\tdefault: %s", flag->defaultValue().c_str());
45 }
46 SkDebugf("\n");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000047 const SkString& help = flag->help();
48 size_t length = help.size();
49 const char* currLine = help.c_str();
50 const char* stop = currLine + length;
51 while (currLine < stop) {
52 if (strlen(currLine) < LINE_LENGTH) {
53 // Only one line length's worth of text left.
54 SkDebugf("\t\t%s\n", currLine);
55 break;
56 }
57 int lineBreak = SkStrFind(currLine, "\n");
58 if (lineBreak < 0 || lineBreak > LINE_LENGTH) {
59 // No line break within line length. Will need to insert one.
60 // Find a space before the line break.
61 int spaceIndex = LINE_LENGTH - 1;
62 while (spaceIndex > 0 && currLine[spaceIndex] != ' ') {
63 spaceIndex--;
64 }
65 int gap;
66 if (0 == spaceIndex) {
67 // No spaces on the entire line. Go ahead and break mid word.
68 spaceIndex = LINE_LENGTH;
69 gap = 0;
70 } else {
71 // Skip the space on the next line
72 gap = 1;
73 }
74 SkDebugf("\t\t%.*s\n", spaceIndex, currLine);
75 currLine += spaceIndex + gap;
76 } else {
77 // the line break is within the limit. Break there.
78 lineBreak++;
79 SkDebugf("\t\t%.*s", lineBreak, currLine);
80 currLine += lineBreak;
81 }
82 }
83 SkDebugf("\n");
84 flag = flag->next();
85 }
86 helpPrinted = true;
87 }
88 if (!helpPrinted) {
89 bool flagMatched = false;
90 SkFlagInfo* flag = gHead;
91 while (flag != NULL) {
92 if (flag->match(argv[i])) {
93 flagMatched = true;
94 switch (flag->getFlagType()) {
95 case SkFlagInfo::kBool_FlagType:
96 // Handled by match, above
97 break;
98 case SkFlagInfo::kString_FlagType:
99 flag->resetStrings();
100 // Add all arguments until another flag is reached.
101 while (i+1 < argc && !SkStrStartsWith(argv[i+1], '-')) {
102 i++;
103 flag->append(argv[i]);
104 }
105 break;
106 case SkFlagInfo::kInt_FlagType:
107 i++;
108 flag->setInt(atoi(argv[i]));
109 break;
110 case SkFlagInfo::kDouble_FlagType:
111 i++;
112 flag->setDouble(atof(argv[i]));
113 break;
114 default:
115 SkASSERT(!"Invalid flag type");
116 }
117 break;
118 }
119 flag = flag->next();
120 }
121 if (!flagMatched) {
122 SkDebugf("skipping unknown flag %s\n", argv[i]);
123 }
124 }
125 }
126 // Since all of the flags have been set, release the memory used by each
127 // flag. FLAGS_x can still be used after this.
128 SkFlagInfo* flag = gHead;
129 gHead = NULL;
130 while (flag != NULL) {
131 SkFlagInfo* next = flag->next();
132 SkDELETE(flag);
133 flag = next;
134 }
135 if (helpPrinted) {
136 exit(0);
137 }
138}