]> git.sur5r.net Git - cc65/blob - src/sp65/attr.c
Move attribute lookup into the output functions. Allow a bytesperline
[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 static int IsNumber (const char* Value)
57 /* Check if Value is an integer number */
58 {
59     if (*Value == '-' || *Value == '+') {
60         ++Value;
61     }
62     while (IsDigit (*Value)) {
63         ++Value;
64     }
65     return (*Value == '\0');
66 }
67
68
69
70 Attr* NewAttr (const char* Name, const char* Value)
71 /* Create a new attribute */
72 {
73     /* Determine the length of Value */
74     unsigned Len = strlen (Value);
75
76     /* Allocate memory */
77     Attr* A = xmalloc (sizeof (Attr) + Len);
78
79     /* Initialize the fields */
80     A->Flags = IsNumber (Value)? afInt : afNone;
81     A->Name  = xstrdup (Name);
82     memcpy (A->Value, Value, Len + 1);
83
84     /* Return the new struct */
85     return A;
86 }
87
88
89
90 void DumpAttrColl (const Collection* C)
91 /* Dump a collection of attribute/value pairs for debugging */
92 {
93     unsigned I;
94     for (I = 0; I < CollCount (C); ++I) {
95         const Attr* A = CollConstAt (C, I);
96         printf ("%s=%s\n", A->Name, A->Value);
97     }
98 }
99
100
101
102 int FindAttr (const Collection* C, const char* Name, unsigned* Index)
103 /* Search for an attribute with the given name in the collection. If it is
104  * found, the function returns true and Index contains the index of the
105  * entry. If Name isn't found, the function returns false and Index
106  * will contain the insert position.
107  */
108 {
109     /* Do a binary search */
110     int Lo = 0;
111     int Hi = (int) CollCount (C) - 1;
112     while (Lo <= Hi) {
113
114         /* Mid of range */
115         int Cur = (Lo + Hi) / 2;
116
117         /* Get item */
118         const Attr* A = CollAt (C, Cur);
119
120         /* Compare */
121         int Res = strcmp (A->Name, Name);
122
123         /* Found? */
124         if (Res < 0) {
125             Lo = Cur + 1;
126         } else if (Res > 0) {
127             Hi = Cur - 1;
128         } else {
129             /* Found! */
130             *Index = Cur;
131             return 1;
132         }
133     }
134
135     /* Pass back the insert position */
136     *Index = Lo;
137     return 0;
138 }
139
140
141
142 const Attr* GetAttr (const Collection* C, const char* Name)
143 /* Search for an attribute with the given name and return it. The function
144  * returns NULL if the attribute wasn't found.
145  */
146 {
147     /* Search for the attribute and return it */
148     unsigned Index;
149     if (FindAttr (C, Name, &Index)) {
150         return CollConstAt (C, Index);
151     } else {
152         /* Not found */
153         return 0;
154     }
155 }
156
157
158
159 const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op)
160 /* Search for an attribute with the given name and return it. If the attribute
161  * is not found, the function terminates with an error using Op as additional
162  * context in the error message.
163  */
164 {
165     /* Search for the attribute and return it */
166     unsigned Index;
167     if (!FindAttr (C, Name, &Index)) {
168         Error ("Found no attribute named `%s' for operation %s", Name, Op);
169     }
170     return CollConstAt (C, Index);
171 }
172
173
174
175 const char* GetAttrVal (const Collection* C, const char* Name)
176 /* Search for an attribute with the given name and return its value. The
177  * function returns NULL if the attribute wasn't found.
178  */
179 {
180     const Attr* A = GetAttr (C, Name);
181     return (A == 0)? 0 : A->Value;
182 }
183
184
185
186 const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op)
187 /* Search for an attribute with the given name and return its value. If the
188  * attribute wasn't not found, the function terminates with an error using
189  * Op as additional context in the error message.
190  */
191 {
192     const Attr* A = NeedAttr (C, Name, Op);
193     return (A == 0)? 0 : A->Value;
194 }
195
196
197
198 void AddAttr (Collection* C, const char* Name, const char* Value)
199 /* Add an attribute to an alphabetically sorted attribute collection */
200 {
201     /* Create a new attribute entry */
202     Attr* A = NewAttr (Name, Value);
203
204     /* Search for the attribute. If it is there, we have a duplicate, otherwise
205      * we have the insert position.
206      */
207     unsigned Index;
208     if (FindAttr (C, Name, &Index)) {
209         Error ("Duplicate command line attribute `%s'", Name);
210     }
211
212     /* Insert the attribute */
213     CollInsert (C, A, Index);
214 }
215
216
217
218 void SplitAddAttr (Collection* C, const char* Combined, const char* Name)
219 /* Split a combined name/value pair and add it as an attribute to C. Some
220  * attributes may not need a name. If the name is missing, use Name. If
221  * Name is NULL, terminate with an error.
222  */
223 {
224     /* Name and value are separated by an equal sign */
225     const char* Pos = strchr (Combined, '=');
226     if (Pos == 0) {
227         /* Combined is actually a value */
228         if (Name == 0) {
229             Error ("Command line attribute `%s' doesn't contain a name", Combined);
230         }
231         AddAttr (C, Name, Combined);
232     } else {
233         /* Must split name and value */
234         StrBuf N = AUTO_STRBUF_INITIALIZER;
235         SB_CopyBuf (&N, Combined, Pos - Combined);
236         SB_Terminate (&N);
237
238         /* Add the attribute */
239         AddAttr (C, SB_GetConstBuf (&N), Pos+1);
240
241         /* Release memory */
242         SB_Done (&N);
243     }                                 
244 }
245
246
247
248 Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount)
249 /* Parse a list containing name/value pairs into a sorted collection. Some
250  * attributes may not need a name, so NameList contains these names. If there
251  * were no errors, the function returns a alphabetically sorted collection
252  * containing Attr entries.
253  */
254 {
255     const char* Name;
256
257     /* Create a new collection */
258     Collection* C = NewCollection ();
259
260     /* Name/value pairs are separated by commas */
261     const char* L = List;
262     StrBuf B = AUTO_STRBUF_INITIALIZER;
263     while (1) {
264         if (*L == ',' || *L == ':' || *L == '\0') {
265
266             /* Terminate the string */
267             SB_Terminate (&B);
268
269             /* Determine the default name */
270             if (CollCount (C) >= NameCount) {
271                 Name = 0;
272             } else {
273                 Name = NameList[CollCount (C)];
274             }
275
276             /* Split and add this attribute/value pair */
277             SplitAddAttr (C, SB_GetConstBuf (&B), Name);
278
279             /* Done, clear the buffer. */
280             SB_Clear (&B);
281             if (*L == '\0') {
282                 break;
283             }
284         } else {
285             SB_AppendChar (&B, *L);
286         }
287         ++L;
288     }
289
290     /* Free memory */
291     SB_Done (&B);
292
293     /* Return the collection with the attributes */
294     return C;
295 }
296
297
298