]> git.sur5r.net Git - cc65/blob - src/sp65/attr.c
Renamed a C header.
[cc65] / src / sp65 / attr.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  attr.c                                   */
4 /*                                                                           */
5 /*                          Command line attributes                          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2012,      Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <string.h>
38
39 /* common */
40 #include "chartype.h"
41 #include "strbuf.h"
42 #include "xmalloc.h"
43
44 /* sp65 */
45 #include "attr.h"
46 #include "error.h"
47
48
49
50 /*****************************************************************************/
51 /*                                   Code                                    */
52 /*****************************************************************************/
53
54
55
56 Attr* NewAttr (const char* Name, const char* Value)
57 /* Create a new attribute */
58 {
59     /* Determine the string lengths */
60     unsigned NameLen  = strlen (Name);
61     unsigned ValueLen = strlen (Value);
62
63     /* Allocate memory */
64     Attr* A = xmalloc (sizeof (Attr) + ValueLen + NameLen + 1);
65
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);
70
71     /* Return the new struct */
72     return A;
73 }
74
75
76
77 void FreeAttr (Attr* A)
78 /* Free an attribute structure */
79 {
80     xfree (A);
81 }
82
83
84
85 void DumpAttrColl (const Collection* C)
86 /* Dump a collection of attribute/value pairs for debugging */
87 {
88     unsigned I;
89     for (I = 0; I < CollCount (C); ++I) {
90         const Attr* A = CollConstAt (C, I);
91         printf ("%s=%s\n", A->Name, A->Value);
92     }
93 }
94
95
96
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.
102 */
103 {
104     /* Do a binary search */
105     int Lo = 0;
106     int Hi = (int) CollCount (C) - 1;
107     while (Lo <= Hi) {
108
109         /* Mid of range */
110         int Cur = (Lo + Hi) / 2;
111
112         /* Get item */
113         const Attr* A = CollAt (C, Cur);
114
115         /* Compare */
116         int Res = strcmp (A->Name, Name);
117
118         /* Found? */
119         if (Res < 0) {
120             Lo = Cur + 1;
121         } else if (Res > 0) {
122             Hi = Cur - 1;
123         } else {
124             /* Found! */
125             *Index = Cur;
126             return 1;
127         }
128     }
129
130     /* Pass back the insert position */
131     *Index = Lo;
132     return 0;
133 }
134
135
136
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.
140 */
141 {
142     /* Search for the attribute and return it */
143     unsigned Index;
144     if (FindAttr (C, Name, &Index)) {
145         return CollConstAt (C, Index);
146     } else {
147         /* Not found */
148         return 0;
149     }
150 }
151
152
153
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.
158 */
159 {
160     /* Search for the attribute and return it */
161     unsigned Index;
162     if (!FindAttr (C, Name, &Index)) {
163         Error ("Found no attribute named '%s' for operation %s", Name, Op);
164     }
165     return CollConstAt (C, Index);
166 }
167
168
169
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.
173 */
174 {
175     const Attr* A = GetAttr (C, Name);
176     return (A == 0)? 0 : A->Value;
177 }
178
179
180
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.
185 */
186 {
187     const Attr* A = NeedAttr (C, Name, Op);
188     return (A == 0)? 0 : A->Value;
189 }
190
191
192
193 void AddAttr (Collection* C, const char* Name, const char* Value)
194 /* Add an attribute to an alphabetically sorted attribute collection */
195 {
196     /* Create a new attribute entry */
197     Attr* A = NewAttr (Name, Value);
198
199     /* Search for the attribute. If it is there, we have a duplicate, otherwise
200     ** we have the insert position.
201     */
202     unsigned Index;
203     if (FindAttr (C, Name, &Index)) {
204         Error ("Duplicate command line attribute '%s'", Name);
205     }
206
207     /* Insert the attribute */
208     CollInsert (C, A, Index);
209 }
210
211
212
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.
217 */
218 {
219     /* Name and value are separated by an equal sign */
220     const char* Pos = strchr (Combined, '=');
221     if (Pos == 0) {
222         /* Combined is actually a value */
223         if (Name == 0) {
224             Error ("Command line attribute '%s' doesn't contain a name", Combined);
225         }
226         AddAttr (C, Name, Combined);
227     } else {
228         /* Must split name and value */
229         StrBuf N = AUTO_STRBUF_INITIALIZER;
230         SB_CopyBuf (&N, Combined, Pos - Combined);
231         SB_Terminate (&N);
232
233         /* Add the attribute */
234         AddAttr (C, SB_GetConstBuf (&N), Pos+1);
235
236         /* Release memory */
237         SB_Done (&N);
238     }
239 }
240
241
242
243 Collection* ParseAttrList (const char* List, const char* const* 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.
248 */
249 {
250     const char* Name;
251
252     /* Create a new collection */
253     Collection* C = NewCollection ();
254
255     /* Name/value pairs are separated by commas */
256     const char* L = List;
257     StrBuf B = AUTO_STRBUF_INITIALIZER;
258     while (1) {
259         if (*L == ',' || *L == ':' || *L == '\0') {
260
261             /* Terminate the string */
262             SB_Terminate (&B);
263
264             /* Determine the default name */
265             if (CollCount (C) >= NameCount) {
266                 Name = 0;
267             } else {
268                 Name = NameList[CollCount (C)];
269             }
270
271             /* Split and add this attribute/value pair */
272             SplitAddAttr (C, SB_GetConstBuf (&B), Name);
273
274             /* Done, clear the buffer. */
275             SB_Clear (&B);
276             if (*L == '\0') {
277                 break;
278             }
279         } else {
280             SB_AppendChar (&B, *L);
281         }
282         ++L;
283     }
284
285     /* Free memory */
286     SB_Done (&B);
287
288     /* Return the collection with the attributes */
289     return C;
290 }
291
292
293
294 void FreeAttrList (Collection* C)
295 /* Free a list of attributes */
296 {
297     unsigned I;
298
299     /* Walk over the collection and free all attributes */
300     for (I = 0; I < CollCount (C); ++I) {
301         FreeAttr (CollAtUnchecked (C, I));
302     }
303
304     /* Free the collection itself */
305     FreeCollection (C);
306 }