* as/hc08/lkaomf51.c (OutputName),
[fw/sdcc] / src / SDCCutil.c
1 /*-------------------------------------------------------------------------
2   SDCCutil.c - Small utility functions.
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include <math.h>
26
27 #ifdef _WIN32
28 #include <ctype.h>
29 #include <windows.h>
30 #endif
31 #include <sys/stat.h>
32 #include "dbuf.h"
33 #include "SDCCglobl.h"
34 #include "SDCCmacro.h"
35 #include "SDCCutil.h"
36 #include "newalloc.h"
37 #ifndef _WIN32
38 #include "findme.h"
39 #endif
40
41 #include "version.h"
42
43 /** Given an array of name, value string pairs creates a new hash
44     containing all of the pairs.
45 */
46 hTab *
47 populateStringHash(const char **pin)
48 {
49   hTab *pret = NULL;
50
51   while (*pin)
52     {
53       shash_add (&pret, pin[0], pin[1]);
54       pin += 2;
55     }
56
57   return pret;
58 }
59
60 /** Prints elements of the set to the file, each element on new line
61 */
62 void
63 fputStrSet(FILE *fp, set *list)
64 {
65   const char *s;
66
67   for (s = setFirstItem(list); s != NULL; s = setNextItem(list)) {
68     fputs(s, fp);
69     fputc('\n', fp);
70   }
71 }
72
73 /** Prepend / append given strings to each item of string set. The result is in a
74     new string set.
75 */
76 set *
77 appendStrSet(set *list, const char *pre, const char *post)
78 {
79   set *new_list = NULL;
80   const char *item;
81   struct dbuf_s dbuf;
82
83   for (item = setFirstItem(list); item != NULL; item = setNextItem(list)) {
84     dbuf_init(&dbuf, PATH_MAX);
85     if (pre != NULL)
86       dbuf_append(&dbuf, pre, strlen(pre));
87     dbuf_append(&dbuf, item, strlen(item));
88     if (post != NULL)
89       dbuf_append(&dbuf, post, strlen(post));
90     addSet(&new_list, (void *)dbuf_c_str(&dbuf));
91     dbuf_detach(&dbuf);
92   }
93
94   return new_list;
95 }
96
97 /** Given a set returns a string containing all of the strings seperated
98     by spaces. The returned string is on the heap.
99 */
100 const char *
101 joinStrSet(set *list)
102 {
103   const char *s;
104   struct dbuf_s dbuf;
105
106   dbuf_init(&dbuf, PATH_MAX);
107
108   for (s = setFirstItem(list); s != NULL; s = setNextItem(list))
109     {
110       dbuf_append(&dbuf, s, strlen(s));
111       dbuf_append(&dbuf, " ", 1);
112     }
113
114   s = dbuf_c_str(&dbuf);
115   dbuf_detach(&dbuf);
116   return s;
117 }
118
119 /** Given a file with path information in the binary files directory,
120     returns the directory component. Used for discovery of bin
121     directory of SDCC installation. Returns NULL if the path is
122     impossible.
123 */
124 #ifdef _WIN32
125 char *
126 getBinPath(const char *prel)
127 {
128   char *p;
129   size_t len;
130   static char path[PATH_MAX];
131     
132   /* try DOS and *nix dir separator on WIN32 */
133   if (NULL != (p = strrchr(prel, DIR_SEPARATOR_CHAR)) ||
134     NULL != (p = strrchr(prel, UNIX_DIR_SEPARATOR_CHAR))) {
135     len = min((sizeof path) - 1, p - prel);
136     strncpy(path, prel, len);
137     path[len] = '\0';
138     return path;
139   }
140   /* not enough info in prel; do it with module name */
141   else if (0 != GetModuleFileName(NULL, path, sizeof path) &&
142     NULL != (p = strrchr(path, DIR_SEPARATOR_CHAR))) {
143     *p = '\0';
144     return path;
145   }
146   else
147     return NULL;
148 }
149 #else
150 char *
151 getBinPath(const char *prel)
152 {
153   static char path[PATH_MAX];
154   const char *ret_path;
155
156   if (NULL != (ret_path = findProgramPath(prel))) {
157     char *p;
158     size_t len;
159
160     if (NULL != (p = strrchr(ret_path, DIR_SEPARATOR_CHAR)) &&
161       PATH_MAX > (len = p - ret_path)) {
162       memcpy(path, ret_path, len);
163       path[len] = '\0';
164       free((void *)ret_path);
165
166       return path;
167     }
168     else {
169       free((void *)ret_path);
170
171       return NULL;
172     }
173   }
174   else
175     return NULL;
176 }
177 #endif
178
179 /** Returns true if the given path exists.
180  */
181 bool
182 pathExists (const char *ppath)
183 {
184   struct stat s;
185
186   return stat (ppath, &s) == 0;
187 }
188
189 static hTab *_mainValues;
190
191 void
192 setMainValue (const char *pname, const char *pvalue)
193 {
194   assert(pname);
195
196   shash_add (&_mainValues, pname, pvalue);
197 }
198
199 void
200 buildCmdLine2 (char *pbuffer, size_t len, const char *pcmd, ...)
201 {
202   va_list ap;
203   char *poutcmd;
204
205   assert(pbuffer && pcmd);
206   assert(_mainValues);
207
208   va_start(ap, pcmd);
209
210   poutcmd = mvsprintf(_mainValues, pcmd, ap);
211
212   va_end(ap);
213
214   strncpyz(pbuffer, poutcmd, len);
215   Safe_free(poutcmd);
216 }
217
218 void
219 populateMainValues (const char **ppin)
220 {
221   _mainValues = populateStringHash(ppin);
222 }
223
224 /** Returns true if sz starts with the string given in key.
225  */
226 bool
227 startsWith (const char *sz, const char *key)
228 {
229   return !strncmp (sz, key, strlen (key));
230 }
231
232 /** Removes any newline characters from the string.  Not strictly the
233     same as perl's chomp.
234 */
235 void
236 chomp (char *sz)
237 {
238   char *nl;
239   while ((nl = strrchr (sz, '\n')))
240     *nl = '\0';
241 }
242
243 hTab *
244 getRuntimeVariables(void)
245 {
246   return _mainValues;
247 }
248
249
250 /* strncpy() with guaranteed NULL termination. */
251 char *strncpyz(char *dest, const char *src, size_t n)
252 {
253     assert(n > 0);
254
255     --n;
256     /* paranoia... */
257     if (strlen(src) > n)
258     {
259         fprintf(stderr, "strncpyz prevented buffer overrun!\n");
260     }
261     
262     strncpy(dest, src, n);
263     dest[n] = 0;
264     return dest;
265 }
266
267 /* like strncat() with guaranteed NULL termination
268  * The passed size should be the size of the dest buffer, not the number of 
269  * bytes to copy.
270  */
271 char *strncatz(char *dest, const char *src, size_t n)
272 {
273     size_t maxToCopy;
274     size_t destLen = strlen(dest);
275     
276     assert(n > 0);
277     assert(n > destLen);
278     
279     maxToCopy = n - destLen - 1;
280     
281     /* paranoia... */
282     if (strlen(src) + destLen >= n)
283     {
284         fprintf(stderr, "strncatz prevented buffer overrun!\n");
285     }
286     
287     strncat(dest, src, maxToCopy);
288     dest[n - 1] = 0;
289     return dest;
290 }
291
292
293 /*-----------------------------------------------------------------*/
294 /* getBuildNumber - return build number                            */
295 /*-----------------------------------------------------------------*/
296 const char *getBuildNumber(void)
297 {
298   return (SDCC_BUILD_NUMBER);
299 }
300
301 #if defined(HAVE_VSNPRINTF) || defined(HAVE_VSPRINTF)
302 size_t SDCCsnprintf(char *dst, size_t n, const char *fmt, ...)
303 {
304   va_list args;
305   int len;
306
307   va_start(args, fmt);
308
309 # if defined(HAVE_VSNPRINTF)
310   len = vsnprintf(dst, n, fmt, args);
311 # else
312   vsprintf(dst, fmt, args);
313   len = strlen(dst) + 1;
314 # endif
315
316   va_end(args);
317
318   /* on some gnu systems, vsnprintf returns -1 if output is truncated.
319    * In the C99 spec, vsnprintf returns the number of characters that 
320    * would have been written, were space available.
321    */
322   if ((len < 0) || (size_t) len >= n) {
323     fprintf(stderr, "internal error: sprintf truncated.\n");
324   }
325
326   return len;
327 }
328
329 #endif