1 /*
2  * routine.c
3  *
4  * general use routines
5  * Copyright (c) 1988-1993 Miguel Santana
6  * Copyright (c) 1995-1999 Akim Demaille, Miguel Santana
7  * $Id$
8  */
9 
10 /*
11  * This file is part of a2ps.
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; see the file COPYING.  If not, write to
25  * the Free Software Foundation, 59 Temple Place - Suite 330,
26  * Boston, MA 02111-1307, USA.
27  */
28 
29 #include "a2ps.h"
30 #include "routines.h"
31 #include "stpncpy.h"
32 #include "message.h"
33 #include "quotearg.h"
34 
35 
36 /*
37  * Convert a list of string of valid chars to an yes/no array
38  */
39 void
string_to_array(uchar arr[256],const uchar * string)40 string_to_array (uchar arr[256], const uchar * string)
41 {
42   int c;
43 
44   for (c = 0 ; c < 256 ; c++)
45     arr [c] = false;
46   for ( /* nothing */ ; *string ; string ++)
47     arr [*string] = true;
48 }
49 
50 /*
51  * Concatenation of a char. No malloc is done.
52  */
53 void
ustrccat(uchar * string,uchar c)54 ustrccat (uchar * string, uchar c)
55 {
56   int len = strlen((char *)string);
57   *(string+len) = c;
58   *(string+len+1) = '\0';
59 }
60 
61 /*
62  * return true iff there are no upper case chars
63  */
64 int
is_strlower(const uchar * string)65 is_strlower (const uchar * string)
66 {
67   for (/* skip */; *string != '\0'; string++)
68     if (isupper(*string))
69       return false;
70   return true;
71 }
72 
73 /* Copy the LEN first characters of SRC into DST in lower case.
74    DST[LEN] is set to \0.  */
75 
76 static inline uchar *
_strncpylc(uchar * dst,const uchar * src,size_t len)77 _strncpylc (uchar *dst, const uchar *src, size_t len)
78 {
79   size_t i;
80   for (i = 0 ; i < len ; i++)
81     dst[i] = tolower (src[i]);
82   dst[len] = '\0';
83   return dst;
84 }
85 
86 uchar *
strnlower(uchar * string,size_t len)87 strnlower (uchar *string, size_t len)
88 {
89   return _strncpylc (string, string, len);
90 }
91 
92 uchar *
strlower(uchar * string)93 strlower (uchar *string)
94 {
95   return _strncpylc (string, string, strlen (string));
96 }
97 
98 uchar *
strcpylc(uchar * dst,const uchar * src)99 strcpylc (uchar *dst, const uchar *src)
100 {
101   return _strncpylc (dst, src, strlen (src));
102 }
103 
104 /*
105  * Count the number of occurrence of C in S
106  */
107 int
strcnt(uchar * s,uchar c)108 strcnt (uchar *s, uchar c)
109 {
110   int res;
111   for (res = 0 ; *s ; s++)
112     if (*s == c)
113       res++;
114   return res;
115 }
116 
117 /*
118  * Extract a substring for START, of LENGTH, making sure to
119  * set the trailing '\0' (return pos of \0)
120  */
121 char *
strsub(char * dest,const char * string,int start,int length)122 strsub (char * dest, const char * string, int start, int length)
123 {
124   char * end = stpncpy (dest, string + start, length);
125   *end = '\0';
126   return end;
127 }
128 
129 /*
130  * fopen, but exits on failure
131  */
132 static inline FILE *
_xfopen(const char * filename,const char * rights,const char * format)133 _xfopen (const char * filename, const char * rights, const char * format)
134 {
135   FILE * res;
136 
137   message (msg_file,
138 	   (stderr, "%s-fopen (%s)\n", rights, quotearg (filename)));
139   res = fopen (filename, rights);
140   if (!res)
141     error (1, errno, format, quotearg (filename));
142   return res;
143 }
144 
145 FILE *
xfopen(const char * filename,const char * rights,const char * format)146 xfopen (const char * filename, const char * rights, const char * format)
147 {
148   return _xfopen (filename, rights, format);
149 }
150 
151 FILE *
xrfopen(const char * filename)152 xrfopen (const char * filename)
153 {
154   return _xfopen (filename, "r", _("cannot open file `%s'"));
155 }
156 
157 FILE *
xwfopen(const char * filename)158 xwfopen (const char * filename)
159 {
160   return _xfopen (filename, "w", _("cannot create file `%s'"));
161 }
162 
163 
164 
165 /*
166  * Like popen, but exist upon failure
167  */
168 static inline FILE *
_xpopen(const char * filename,const char * rights,const char * format)169 _xpopen (const char * filename, const char * rights, const char * format)
170 {
171   FILE * res;
172 
173   message (msg_file,
174 	   (stderr, "%s-popen (%s)\n", rights, filename));
175   res = popen (filename, rights);
176   if (!res)
177     error (1, errno, format, quotearg (filename));
178   return res;
179 }
180 
181 FILE *
xpopen(const char * filename,const char * rights,const char * format)182 xpopen (const char * filename, const char * rights, const char * format)
183 {
184   return _xpopen (filename, rights, format);
185 }
186 
187 FILE *
xrpopen(const char * filename)188 xrpopen (const char * filename)
189 {
190   return _xpopen (filename, "r", _("cannot open a pipe on `%s'"));
191 }
192 
193 FILE *
xwpopen(const char * filename)194 xwpopen (const char * filename)
195 {
196   return _xpopen (filename, "w", _("cannot open a pipe on `%s'"));
197 }
198 
199 /*
200  * Copy the content of IN into OUT
201  */
202 static inline void
_streams_copy(FILE * in,FILE * out)203 _streams_copy (FILE * in, FILE * out)
204 {
205   size_t read_length;
206   char buf [BUFSIZ];
207 
208   while ((read_length = fread (buf, sizeof (char), sizeof (buf), in)))
209     fwrite (buf, sizeof (char), read_length, out);
210 }
211 
212 void
streams_copy(FILE * in,FILE * out)213 streams_copy (FILE * in, FILE * out)
214 {
215   _streams_copy (in, out);
216 }
217 
218 /*
219  * Dump the content of the file FILENAME onto STREAM.
220  * Used when honoring a subcontract.
221  */
222 void
stream_dump(FILE * stream,const char * filename)223 stream_dump (FILE * stream, const char * filename)
224 {
225   FILE * fp;
226 
227   message (msg_tool | msg_file, (stderr, "Dumping file `%s'\n", filename));
228 
229   fp = xrfopen (filename);
230   _streams_copy (fp, stream);
231   fclose (fp);
232 }
233 
234 /*
235  * Unlink the file FILENAME.
236  */
237 void
unlink2(PARAM_UNUSED void * dummy,const char * filename)238 unlink2 (PARAM_UNUSED void * dummy, const char * filename)
239 {
240   message (msg_tool | msg_file, (stderr, "Unlinking file `%s'\n", filename));
241 
242   /* Don't complain if you can't unlink.  Who cares of a tmp file? */
243   unlink (filename);
244 }
245