1 /*
2  * routines.h -- general use routines
3  * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
4  */
5 
6 /*
7  * This file is part of a2ps.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; see the file COPYING.  If not, write to
21  * the Free Software Foundation, 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24 
25 #ifndef _ROUTINES_H_
26 # define _ROUTINES_H_
27 
28 /*
29  * From xgetcwd.c
30  */
31 char *xgetcwd PARAMS ((void));
32 
33 /*
34  * from xgethostname.c
35  */
36 char *xgethostname PARAMS ((void));
37 
38 char *stpcpy PARAMS ((char * dest, const char * src));
39 char *stpncpy PARAMS ((char * dest, const char * src, size_t n));
40 
41 /*
42  * unsigned char variation of usual functions on strings
43  */
44 #define ustrcat(x,y) 					\
45 	(strcat((char *)(x), (const char *)(y)))
46 
47 #define ustrncat(x,y,n)	\
48 	(strncat(((char *)x), (const char *) y, n))
49 
50 #define ustrcpy(x,y) 					\
51 	(strcpy((char *)(x), (const char *)(y)))
52 #define ustrncpy(x,y,z) 				\
53 	(strncpy((char *)(x), (const char *)(y), (z)))
54 
55 #define ustpcpy(x,y)					\
56 	(stpcpy((char *)(x), (const char *)(y)))
57 #define ustpncpy(x,y,z)					\
58 	(stpncpy((char *)(x), (const char *)(y), (z)))
59 
60 #define ustrcmp(x,y)					\
61 	(strcmp((const char *)(x), (const char *)(y)))
62 #define ustrncmp(x,y,z)					\
63 	(strncmp((const char *)(x), (const char *)(y), (z)))
64 
65 #define ustrlen(x)					\
66 	(strlen((const char *)(x)))
67 
68 #define ustrchr(x,y) 					\
69 	((uchar *) strchr((char *)(x), (int)(y)))
70 #define ustrrchr(x,y) 					\
71 	((uchar *) strrchr((char *)(x), (int)(y)))
72 
73 #define xustrdup(x) 					\
74 	((uchar *) xstrdup((const char *)(x)))
75 
76 #define ustrtok(x,y)					\
77 	((uchar *) strtok ((char *)(x), (const char *)(y)))
78 
79 /*
80  * Put in X a copy of chars in Y from Z to T
81  */
82 #define ustrsub(x,y,z,t)				\
83         ((uchar *) strsub ((char *)(x), (const char *)(y), (z), (t)));
84 
85 /*
86  * A string prefixes another
87  */
88 #define strprefix(s1, s2)				\
89 	(!strncmp(s1, s2, strlen(s1)))
90 #define ustrprefix(s1, s2)				\
91 	(!ustrncmp(s1, s2, ustrlen(s1)))
92 
93 /*
94  * A string is the end of another
95  *
96  * Note that there are too many strlens.  But I know
97  * no other way...
98  */
99 #define strsuffix(s1, s2)				\
100     ((strlen (s1) < strlen (s2))			\
101      ? 0						\
102      : !strcmp (s1 + strlen (s1) - strlen (s2), s2))
103 
104 #define ustrsuffix(s1, s2)				\
105     ((ustrlen (s1) < ustrlen (s2))			\
106      ? 0						\
107      : !ustrcmp (s1 + ustrlen (s1) - ustrlen (s2), s2))
108 
109 /*
110  * Replace a malloc'd string with another
111  */
112 #define xstrcpy(s1, s2)					\
113  do {				       			\
114    const char *my_s2 = (s2);	       			\
115    XFREE (s1);					       	\
116    s1 = !IS_EMPTY (my_s2) ? xstrdup (my_s2) : NULL;	\
117  } while (0)
118 
119 /* We cannot just define this one like
120     xstrcpy ((char *) s1, (const char *) s2);
121    because it will expand into a line like
122     (char *) s1 = ...
123    and AIX 3.2's cc choke on this!!!  It says
124     (S) Operand must be a modifiable lvalue. */
125 
126 #define xustrcpy(s1, s2)				\
127  do {				       			\
128    const uchar *my_s2 = (uchar *) (s2);			\
129    XFREE (s1);					       	\
130    s1 = !IS_EMPTY (my_s2) ? xustrdup (my_s2) : UNULL;	\
131  } while (0)
132 
133 /*
134  * Cut the _STRING_ a the first occurence of the _CHAR_ if there is
135  */
136 #define strcut(_string_, _char_)		\
137   do {						\
138     char * __strcut_cp;				\
139     __strcut_cp = strchr (_string_, _char_);	\
140     if (__strcut_cp)				\
141       *__strcut_cp = '\0';			\
142   } while (0)
143 
144 #define ustrcut(_ustring_, _uchar_)	\
145   strcut ((char *) (_ustring_), (char) _uchar_)
146 
147 /*
148  * Cut the _STRING_ a the last occurence of the _CHAR_ if there is
149  */
150 #define strrcut(_string_, _char_)		\
151   do {						\
152     char * __strrcut_cp;			\
153     __strrcut_cp = strrchr (_string_, _char_);	\
154     if (__strrcut_cp)				\
155       *__strrcut_cp = '\0';			\
156   } while (0)
157 
158 #define ustrrcut(_ustring_, _uchar_)	\
159   strrcut ((char *) (_ustring_), (char) _uchar_)
160 
161 /*
162  * alloca version of some str routines
163  */
164 /*
165   Here is a very interesting part of the GNU libc doc,
166   which explains a problem I had...
167 
168    Do not use `alloca' inside the arguments of a function call--you
169    will get unpredictable results, because the stack space for the
170    `alloca' would appear on the stack in the middle of the space for the
171    function arguments.  An example of what to avoid is `foo (x, alloca
172    (4), y)'.
173 */
174 #define astrcpy(_d_,_s_)				\
175    do {							\
176 	const char * _tmp_ = (const char *) (_s_);	\
177 	_d_ = ALLOCA (char, strlen (_tmp_) + 1);	\
178 	strcpy (_d_, _tmp_);				\
179    } while (0)
180 
181 #define austrcpy(_d_,_s_)				\
182    do {							\
183 	const uchar * _tmp_ = (const uchar *) (_s_);	\
184 	_d_ = ALLOCA (uchar, ustrlen (_tmp_) + 1);	\
185 	ustrcpy (_d_, _tmp_);				\
186    } while (0)
187 
188 #define strcat2(_d_,_s1_,_s2_)		\
189  do {					\
190    stpcpy (stpcpy (_d_, _s1_), _s2_);	\
191  } while (0)
192 
193 #define astrcat2(_d_,_s1_,_s2_)			\
194  do {						\
195    const char * _tmp1_ = (const char *) (_s1_);	\
196    const char * _tmp2_ = (const char *) (_s2_);	\
197    _d_ = ALLOCA (char, (strlen (_tmp1_) 	\
198        		        + strlen (_tmp2_) + 1));\
199    strcat2(_d_,_s1_,_s2_);			\
200  } while (0)
201 
202 /*
203  * Concatenation of a char. No malloc is done.
204  */
205 #define USTRCCAT(s, c)					\
206   do { int __len = strlen((const char *)s);		\
207        *(s+__len) = c;					\
208        *(s+__len+1) = '\0'; 				\
209   } while (false)
210 
211 
212 #define IS_BETWEEN(x, min, max) (((min) <= (x)) && ((x) <= (max)))
213 
214 #define IS_EMPTY(s1)	\
215 	(((const char *) (s1) == NULL) || (*(s1) == '\0'))
216 #define UNNULL(s1)	\
217  ((((void const *) s1) == NULL) ? (const char *) "" : (const char *) (s1))
218 #define ustrequ(s1, s2) (!ustrcmp(s1, s2))
219 #define strcaseequ(s1, s2) (!strcasecmp(s1, s2))
220 
221 /* Functions on strings */
222 void string_to_array PARAMS ((uchar arr[256], const uchar * string));
223 int is_strlower PARAMS((const uchar * string));
224 uchar *strnlower PARAMS ((uchar * string, size_t len));
225 uchar *strlower PARAMS ((uchar * string));
226 uchar *strcpylc PARAMS ((uchar *dst, const uchar *src));
227 
228 void ustrccat PARAMS((uchar * string, uchar c));
229 int strcnt PARAMS((uchar * s, uchar c));
230 char * strsub PARAMS ((char * dest,
231 		       const char * string, int start, int length));
232 
233 /* Copy the content of IN into OUT */
234 void streams_copy PARAMS ((FILE * in, FILE * out));
235 
236 /* Dump the content of a file onto STREAM */
237 void stream_dump PARAMS ((FILE * stream, const char * filename));
238 /* unlink FILENAME */
239 void unlink2 PARAMS ((void* dummy, const char * filename));
240 
241 /* Fopen but exits on failure */
242 FILE * xfopen PARAMS ((const char * filename, const char * rights,
243 		       const char * format));
244 /* opened "r", and "w" */
245 FILE * xrfopen PARAMS ((const char * filename));
246 FILE * xwfopen PARAMS ((const char * filename));
247 
248 /* Popen but exits on failure */
249 FILE * xpopen PARAMS ((const char * command, const char * rights,
250 		       const char * format));
251 /* opened "r", and "w" */
252 FILE * xrpopen PARAMS ((const char * command));
253 FILE * xwpopen PARAMS ((const char * command));
254 
255 /* If _STR_ is not defined, give it a tempname in _TMPDIR_ */
256 #define tempname_ensure(Str)				\
257 do {							\
258   (Str) = (Str) ? (Str) : tempnam (NULL, "a2_");	\
259 } while (0)
260 
261 #endif
262