1 /*****************************************************************************/
5 /* Command line attributes */
9 /* (C) 2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 Attr* NewAttr (const char* Name, const char* Value)
57 /* Create a new attribute */
59 /* Determine the string lengths */
60 unsigned NameLen = strlen (Name);
61 unsigned ValueLen = strlen (Value);
64 Attr* A = xmalloc (sizeof (Attr) + ValueLen + NameLen + 1);
66 /* Initialize the fields */
67 A->Name = A->Value + ValueLen + 1;
68 memcpy (A->Value, Value, ValueLen + 1);
69 memcpy (A->Name, Name, NameLen + 1);
71 /* Return the new struct */
77 void FreeAttr (Attr* A)
78 /* Free an attribute structure */
85 void DumpAttrColl (const Collection* C)
86 /* Dump a collection of attribute/value pairs for debugging */
89 for (I = 0; I < CollCount (C); ++I) {
90 const Attr* A = CollConstAt (C, I);
91 printf ("%s=%s\n", A->Name, A->Value);
97 int FindAttr (const Collection* C, const char* Name, unsigned* Index)
98 /* Search for an attribute with the given name in the collection. If it is
99 * found, the function returns true and Index contains the index of the
100 * entry. If Name isn't found, the function returns false and Index
101 * will contain the insert position.
104 /* Do a binary search */
106 int Hi = (int) CollCount (C) - 1;
110 int Cur = (Lo + Hi) / 2;
113 const Attr* A = CollAt (C, Cur);
116 int Res = strcmp (A->Name, Name);
121 } else if (Res > 0) {
130 /* Pass back the insert position */
137 const Attr* GetAttr (const Collection* C, const char* Name)
138 /* Search for an attribute with the given name and return it. The function
139 * returns NULL if the attribute wasn't found.
142 /* Search for the attribute and return it */
144 if (FindAttr (C, Name, &Index)) {
145 return CollConstAt (C, Index);
154 const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op)
155 /* Search for an attribute with the given name and return it. If the attribute
156 * is not found, the function terminates with an error using Op as additional
157 * context in the error message.
160 /* Search for the attribute and return it */
162 if (!FindAttr (C, Name, &Index)) {
163 Error ("Found no attribute named `%s' for operation %s", Name, Op);
165 return CollConstAt (C, Index);
170 const char* GetAttrVal (const Collection* C, const char* Name)
171 /* Search for an attribute with the given name and return its value. The
172 * function returns NULL if the attribute wasn't found.
175 const Attr* A = GetAttr (C, Name);
176 return (A == 0)? 0 : A->Value;
181 const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op)
182 /* Search for an attribute with the given name and return its value. If the
183 * attribute wasn't not found, the function terminates with an error using
184 * Op as additional context in the error message.
187 const Attr* A = NeedAttr (C, Name, Op);
188 return (A == 0)? 0 : A->Value;
193 void AddAttr (Collection* C, const char* Name, const char* Value)
194 /* Add an attribute to an alphabetically sorted attribute collection */
196 /* Create a new attribute entry */
197 Attr* A = NewAttr (Name, Value);
199 /* Search for the attribute. If it is there, we have a duplicate, otherwise
200 * we have the insert position.
203 if (FindAttr (C, Name, &Index)) {
204 Error ("Duplicate command line attribute `%s'", Name);
207 /* Insert the attribute */
208 CollInsert (C, A, Index);
213 void SplitAddAttr (Collection* C, const char* Combined, const char* Name)
214 /* Split a combined name/value pair and add it as an attribute to C. Some
215 * attributes may not need a name. If the name is missing, use Name. If
216 * Name is NULL, terminate with an error.
219 /* Name and value are separated by an equal sign */
220 const char* Pos = strchr (Combined, '=');
222 /* Combined is actually a value */
224 Error ("Command line attribute `%s' doesn't contain a name", Combined);
226 AddAttr (C, Name, Combined);
228 /* Must split name and value */
229 StrBuf N = AUTO_STRBUF_INITIALIZER;
230 SB_CopyBuf (&N, Combined, Pos - Combined);
233 /* Add the attribute */
234 AddAttr (C, SB_GetConstBuf (&N), Pos+1);
243 Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount)
244 /* Parse a list containing name/value pairs into a sorted collection. Some
245 * attributes may not need a name, so NameList contains these names. If there
246 * were no errors, the function returns a alphabetically sorted collection
247 * containing Attr entries.
252 /* Create a new collection */
253 Collection* C = NewCollection ();
255 /* Name/value pairs are separated by commas */
256 const char* L = List;
257 StrBuf B = AUTO_STRBUF_INITIALIZER;
259 if (*L == ',' || *L == ':' || *L == '\0') {
261 /* Terminate the string */
264 /* Determine the default name */
265 if (CollCount (C) >= NameCount) {
268 Name = NameList[CollCount (C)];
271 /* Split and add this attribute/value pair */
272 SplitAddAttr (C, SB_GetConstBuf (&B), Name);
274 /* Done, clear the buffer. */
280 SB_AppendChar (&B, *L);
288 /* Return the collection with the attributes */
294 void FreeAttrList (Collection* C)
295 /* Free a list of attributes */
299 /* Walk over the collection and free all attributes */
300 for (I = 0; I < CollCount (C); ++I) {
301 FreeAttr (CollAtUnchecked (C, I));
304 /* Free the collection itself */