Line data Source code
1 : /* stringhelp.c - standard string helper functions
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007,
3 : * 2008, 2009, 2010 Free Software Foundation, Inc.
4 : * Copyright (C) 2014 Werner Koch
5 : * Copyright (C) 2015 g10 Code GmbH
6 : *
7 : * This file is part of GnuPG.
8 : *
9 : * GnuPG is free software; you can redistribute it and/or modify it
10 : * under the terms of either
11 : *
12 : * - the GNU Lesser General Public License as published by the Free
13 : * Software Foundation; either version 3 of the License, or (at
14 : * your option) any later version.
15 : *
16 : * or
17 : *
18 : * - the GNU General Public License as published by the Free
19 : * Software Foundation; either version 2 of the License, or (at
20 : * your option) any later version.
21 : *
22 : * or both in parallel, as here.
23 : *
24 : * GnuPG is distributed in the hope that it will be useful, but
25 : * WITHOUT ANY WARRANTY; without even the implied warranty of
26 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 : * General Public License for more details.
28 : *
29 : * You should have received a copies of the GNU General Public License
30 : * and the GNU Lesser General Public License along with this program;
31 : * if not, see <https://www.gnu.org/licenses/>.
32 : */
33 :
34 : #include <config.h>
35 : #include <stdlib.h>
36 : #include <string.h>
37 : #include <stdarg.h>
38 : #include <ctype.h>
39 : #include <errno.h>
40 : #ifdef HAVE_PWD_H
41 : # include <pwd.h>
42 : #endif
43 : #include <unistd.h>
44 : #include <sys/types.h>
45 : #ifdef HAVE_W32_SYSTEM
46 : # ifdef HAVE_WINSOCK2_H
47 : # include <winsock2.h>
48 : # endif
49 : # include <windows.h>
50 : #endif
51 : #include <assert.h>
52 : #include <limits.h>
53 :
54 : #include "util.h"
55 : #include "common-defs.h"
56 : #include "utf8conv.h"
57 : #include "sysutils.h"
58 : #include "stringhelp.h"
59 :
60 : #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
61 :
62 :
63 : /* Sometimes we want to avoid mixing slashes and backslashes on W32
64 : and prefer backslashes. There is usual no problem with mixing
65 : them, however a very few W32 API calls can't grok plain slashes.
66 : Printing filenames with mixed slashes also looks a bit strange.
67 : This function has no effext on POSIX. */
68 : static inline char *
69 17166 : change_slashes (char *name)
70 : {
71 : #ifdef HAVE_DOSISH_SYSTEM
72 : char *p;
73 :
74 : if (strchr (name, '\\'))
75 : {
76 : for (p=name; *p; p++)
77 : if (*p == '/')
78 : *p = '\\';
79 : }
80 : #endif /*HAVE_DOSISH_SYSTEM*/
81 17166 : return name;
82 : }
83 :
84 :
85 : /*
86 : * Check whether STRING starts with KEYWORD. The keyword is
87 : * delimited by end of string, a space or a tab. Returns NULL if not
88 : * found or a pointer into STRING to the next non-space character
89 : * after the KEYWORD (which may be end of string).
90 : */
91 : char *
92 1894 : has_leading_keyword (const char *string, const char *keyword)
93 : {
94 1894 : size_t n = strlen (keyword);
95 :
96 1894 : if (!strncmp (string, keyword, n)
97 783 : && (!string[n] || string[n] == ' ' || string[n] == '\t'))
98 : {
99 783 : string += n;
100 2049 : while (*string == ' ' || *string == '\t')
101 483 : string++;
102 783 : return (char*)string;
103 : }
104 1111 : return NULL;
105 : }
106 :
107 :
108 : /*
109 : * Look for the substring SUB in buffer and return a pointer to that
110 : * substring in BUFFER or NULL if not found.
111 : * Comparison is case-insensitive.
112 : */
113 : const char *
114 44 : memistr (const void *buffer, size_t buflen, const char *sub)
115 : {
116 44 : const unsigned char *buf = buffer;
117 44 : const unsigned char *t = (const unsigned char *)buffer;
118 44 : const unsigned char *s = (const unsigned char *)sub;
119 44 : size_t n = buflen;
120 :
121 232 : for ( ; n ; t++, n-- )
122 : {
123 214 : if ( toupper (*t) == toupper (*s) )
124 : {
125 234 : for ( buf=t++, buflen = n--, s++;
126 310 : n && toupper (*t) == toupper (*s); t++, s++, n-- )
127 : ;
128 46 : if (!*s)
129 26 : return (const char*)buf;
130 20 : t = buf;
131 20 : s = (const unsigned char *)sub ;
132 20 : n = buflen;
133 : }
134 : }
135 18 : return NULL;
136 : }
137 :
138 : const char *
139 1 : ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
140 : {
141 1 : const unsigned char *buf = buffer;
142 1 : const unsigned char *t = (const unsigned char *)buf;
143 1 : const unsigned char *s = (const unsigned char *)sub;
144 1 : size_t n = buflen;
145 :
146 1 : for ( ; n ; t++, n-- )
147 : {
148 1 : if (ascii_toupper (*t) == ascii_toupper (*s) )
149 : {
150 6 : for ( buf=t++, buflen = n--, s++;
151 9 : n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
152 : ;
153 1 : if (!*s)
154 1 : return (const char*)buf;
155 0 : t = (const unsigned char *)buf;
156 0 : s = (const unsigned char *)sub ;
157 0 : n = buflen;
158 : }
159 : }
160 0 : return NULL;
161 : }
162 :
163 : /* This function is similar to strncpy(). However it won't copy more
164 : than N - 1 characters and makes sure that a '\0' is appended. With
165 : N given as 0, nothing will happen. With DEST given as NULL, memory
166 : will be allocated using xmalloc (i.e. if it runs out of core
167 : the function terminates). Returns DES or a pointer to the
168 : allocated memory.
169 : */
170 : char *
171 383 : mem2str( char *dest , const void *src , size_t n )
172 : {
173 : char *d;
174 : const char *s;
175 :
176 383 : if( n ) {
177 383 : if( !dest )
178 0 : dest = xmalloc( n ) ;
179 383 : d = dest;
180 383 : s = src ;
181 5887 : for(n--; n && *s; n-- )
182 5504 : *d++ = *s++;
183 383 : *d = '\0' ;
184 : }
185 :
186 383 : return dest ;
187 : }
188 :
189 :
190 : /****************
191 : * remove leading and trailing white spaces
192 : */
193 : char *
194 1371 : trim_spaces( char *str )
195 : {
196 : char *string, *p, *mark;
197 :
198 1371 : string = str;
199 : /* find first non space character */
200 1371 : for( p=string; *p && isspace( *(byte*)p ) ; p++ )
201 : ;
202 : /* move characters */
203 86374 : for( (mark = NULL); (*string = *p); string++, p++ )
204 85003 : if( isspace( *(byte*)p ) ) {
205 62 : if( !mark )
206 58 : mark = string ;
207 : }
208 : else
209 84941 : mark = NULL ;
210 1371 : if( mark )
211 56 : *mark = '\0' ; /* remove trailing spaces */
212 :
213 1371 : return str ;
214 : }
215 :
216 : /****************
217 : * remove trailing white spaces
218 : */
219 : char *
220 0 : trim_trailing_spaces( char *string )
221 : {
222 : char *p, *mark;
223 :
224 0 : for( mark = NULL, p = string; *p; p++ ) {
225 0 : if( isspace( *(byte*)p ) ) {
226 0 : if( !mark )
227 0 : mark = p;
228 : }
229 : else
230 0 : mark = NULL;
231 : }
232 0 : if( mark )
233 0 : *mark = '\0' ;
234 :
235 0 : return string ;
236 : }
237 :
238 :
239 : unsigned
240 5502 : trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
241 : {
242 : byte *p, *mark;
243 : unsigned n;
244 :
245 224420 : for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
246 218918 : if( strchr(trimchars, *p ) ) {
247 40792 : if( !mark )
248 34749 : mark = p;
249 : }
250 : else
251 178126 : mark = NULL;
252 : }
253 :
254 5502 : if( mark ) {
255 5437 : *mark = 0;
256 5437 : return mark - line;
257 : }
258 65 : return len;
259 : }
260 :
261 : /****************
262 : * remove trailing white spaces and return the length of the buffer
263 : */
264 : unsigned
265 30 : trim_trailing_ws( byte *line, unsigned len )
266 : {
267 30 : return trim_trailing_chars( line, len, " \t\r\n" );
268 : }
269 :
270 : size_t
271 380 : length_sans_trailing_chars (const unsigned char *line, size_t len,
272 : const char *trimchars )
273 : {
274 : const unsigned char *p, *mark;
275 : size_t n;
276 :
277 4626 : for( mark=NULL, p=line, n=0; n < len; n++, p++ )
278 : {
279 4246 : if (strchr (trimchars, *p ))
280 : {
281 797 : if( !mark )
282 797 : mark = p;
283 : }
284 : else
285 3449 : mark = NULL;
286 : }
287 :
288 380 : if (mark)
289 380 : return mark - line;
290 0 : return len;
291 : }
292 :
293 : /*
294 : * Return the length of line ignoring trailing white-space.
295 : */
296 : size_t
297 380 : length_sans_trailing_ws (const unsigned char *line, size_t len)
298 : {
299 380 : return length_sans_trailing_chars (line, len, " \t\r\n");
300 : }
301 :
302 :
303 :
304 : /*
305 : * Extract from a given path the filename component. This function
306 : * terminates the process on memory shortage.
307 : */
308 : char *
309 334 : make_basename(const char *filepath, const char *inputpath)
310 : {
311 : #ifdef __riscos__
312 : return riscos_make_basename(filepath, inputpath);
313 : #else
314 : char *p;
315 :
316 : (void)inputpath; /* Only required for riscos. */
317 :
318 334 : if ( !(p=strrchr(filepath, '/')) )
319 : #ifdef HAVE_DOSISH_SYSTEM
320 : if ( !(p=strrchr(filepath, '\\')) )
321 : #endif
322 : #ifdef HAVE_DRIVE_LETTERS
323 : if ( !(p=strrchr(filepath, ':')) )
324 : #endif
325 : {
326 334 : return xstrdup(filepath);
327 : }
328 :
329 0 : return xstrdup(p+1);
330 : #endif
331 : }
332 :
333 :
334 :
335 : /*
336 : * Extract from a given filename the path prepended to it. If there
337 : * isn't a path prepended to the filename, a dot is returned ('.').
338 : * This function terminates the process on memory shortage.
339 : */
340 : char *
341 33 : make_dirname(const char *filepath)
342 : {
343 : char *dirname;
344 : int dirname_length;
345 : char *p;
346 :
347 33 : if ( !(p=strrchr(filepath, '/')) )
348 : #ifdef HAVE_DOSISH_SYSTEM
349 : if ( !(p=strrchr(filepath, '\\')) )
350 : #endif
351 : #ifdef HAVE_DRIVE_LETTERS
352 : if ( !(p=strrchr(filepath, ':')) )
353 : #endif
354 : {
355 0 : return xstrdup(".");
356 : }
357 :
358 33 : dirname_length = p-filepath;
359 33 : dirname = xmalloc(dirname_length+1);
360 33 : strncpy(dirname, filepath, dirname_length);
361 33 : dirname[dirname_length] = 0;
362 :
363 33 : return dirname;
364 : }
365 :
366 :
367 :
368 : static char *
369 0 : get_pwdir (int xmode, const char *name)
370 : {
371 0 : char *result = NULL;
372 : #ifdef HAVE_PWD_H
373 0 : struct passwd *pwd = NULL;
374 :
375 0 : if (name)
376 : {
377 : #ifdef HAVE_GETPWNAM
378 : /* Fixme: We should use getpwnam_r if available. */
379 0 : pwd = getpwnam (name);
380 : #endif
381 : }
382 : else
383 : {
384 : #ifdef HAVE_GETPWUID
385 : /* Fixme: We should use getpwuid_r if available. */
386 0 : pwd = getpwuid (getuid());
387 : #endif
388 : }
389 0 : if (pwd)
390 : {
391 0 : if (xmode)
392 0 : result = xstrdup (pwd->pw_dir);
393 : else
394 0 : result = xtrystrdup (pwd->pw_dir);
395 : }
396 : #else /*!HAVE_PWD_H*/
397 : /* No support at all. */
398 : (void)xmode;
399 : (void)name;
400 : #endif /*HAVE_PWD_H*/
401 0 : return result;
402 : }
403 :
404 :
405 : /* xmode 0 := Return NULL on error
406 : 1 := Terminate on error
407 : 2 := Make sure that name is absolute; return NULL on error
408 : 3 := Make sure that name is absolute; terminate on error
409 : */
410 : static char *
411 17168 : do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
412 : {
413 : const char *argv[32];
414 : int argc;
415 : size_t n;
416 17168 : int skip = 1;
417 17168 : char *home_buffer = NULL;
418 : char *name, *home, *p;
419 : int want_abs;
420 :
421 17168 : want_abs = !!(xmode & 2);
422 17168 : xmode &= 1;
423 :
424 17168 : n = strlen (first_part) + 1;
425 17168 : argc = 0;
426 48407 : while ( (argv[argc] = va_arg (arg_ptr, const char *)) )
427 : {
428 14073 : n += strlen (argv[argc]) + 1;
429 14073 : if (argc >= DIM (argv)-1)
430 : {
431 2 : if (xmode)
432 0 : BUG ();
433 2 : gpg_err_set_errno (EINVAL);
434 2 : return NULL;
435 : }
436 14071 : argc++;
437 : }
438 17166 : n++;
439 :
440 17166 : home = NULL;
441 17166 : if (*first_part == '~')
442 : {
443 1651 : if (first_part[1] == '/' || !first_part[1])
444 : {
445 : /* This is the "~/" or "~" case. */
446 1651 : home = getenv("HOME");
447 1651 : if (!home)
448 0 : home = home_buffer = get_pwdir (xmode, NULL);
449 3302 : if (home && *home)
450 1651 : n += strlen (home);
451 : }
452 : else
453 : {
454 : /* This is the "~username/" or "~username" case. */
455 : char *user;
456 :
457 0 : if (xmode)
458 0 : user = xstrdup (first_part+1);
459 : else
460 : {
461 0 : user = xtrystrdup (first_part+1);
462 0 : if (!user)
463 0 : return NULL;
464 : }
465 0 : p = strchr (user, '/');
466 0 : if (p)
467 0 : *p = 0;
468 0 : skip = 1 + strlen (user);
469 :
470 0 : home = home_buffer = get_pwdir (xmode, user);
471 0 : xfree (user);
472 0 : if (home)
473 0 : n += strlen (home);
474 : else
475 0 : skip = 1;
476 : }
477 : }
478 :
479 17166 : if (xmode)
480 16416 : name = xmalloc (n);
481 : else
482 : {
483 750 : name = xtrymalloc (n);
484 750 : if (!name)
485 : {
486 0 : xfree (home_buffer);
487 0 : return NULL;
488 : }
489 : }
490 :
491 17166 : if (home)
492 1651 : p = stpcpy (stpcpy (name, home), first_part + skip);
493 : else
494 15515 : p = stpcpy (name, first_part);
495 :
496 17166 : xfree (home_buffer);
497 31175 : for (argc=0; argv[argc]; argc++)
498 : {
499 : /* Avoid a leading double slash if the first part was "/". */
500 14009 : if (!argc && name[0] == '/' && !name[1])
501 0 : p = stpcpy (p, argv[argc]);
502 : else
503 14009 : p = stpcpy (stpcpy (p, "/"), argv[argc]);
504 : }
505 :
506 17166 : if (want_abs)
507 : {
508 : #ifdef HAVE_DRIVE_LETTERS
509 : p = strchr (name, ':');
510 : if (p)
511 : p++;
512 : else
513 : p = name;
514 : #else
515 4957 : p = name;
516 : #endif
517 4957 : if (*p != '/'
518 : #ifdef HAVE_DRIVE_LETTERS
519 : && *p != '\\'
520 : #endif
521 : )
522 : {
523 3 : home = gnupg_getcwd ();
524 3 : if (!home)
525 : {
526 0 : if (xmode)
527 : {
528 0 : fprintf (stderr, "\nfatal: getcwd failed: %s\n",
529 0 : strerror (errno));
530 0 : exit(2);
531 : }
532 0 : xfree (name);
533 0 : return NULL;
534 : }
535 3 : n = strlen (home) + 1 + strlen (name) + 1;
536 3 : if (xmode)
537 0 : home_buffer = xmalloc (n);
538 : else
539 : {
540 3 : home_buffer = xtrymalloc (n);
541 3 : if (!home_buffer)
542 : {
543 0 : xfree (home);
544 0 : xfree (name);
545 0 : return NULL;
546 : }
547 : }
548 3 : if (p == name)
549 3 : p = home_buffer;
550 : else /* Windows case. */
551 : {
552 0 : memcpy (home_buffer, p, p - name + 1);
553 0 : p = home_buffer + (p - name + 1);
554 : }
555 :
556 : /* Avoid a leading double slash if the cwd is "/". */
557 3 : if (home[0] == '/' && !home[1])
558 0 : strcpy (stpcpy (p, "/"), name);
559 : else
560 3 : strcpy (stpcpy (stpcpy (p, home), "/"), name);
561 :
562 3 : xfree (home);
563 3 : xfree (name);
564 3 : name = home_buffer;
565 : /* Let's do a simple compression to catch the most common
566 : case of using "." for gpg's --homedir option. */
567 3 : n = strlen (name);
568 3 : if (n > 2 && name[n-2] == '/' && name[n-1] == '.')
569 1 : name[n-2] = 0;
570 : }
571 : }
572 17166 : return change_slashes (name);
573 : }
574 :
575 : /* Construct a filename from the NULL terminated list of parts. Tilde
576 : expansion is done for the first argument. This function terminates
577 : the process on memory shortage. */
578 : char *
579 11567 : make_filename (const char *first_part, ... )
580 : {
581 : va_list arg_ptr;
582 : char *result;
583 :
584 11567 : va_start (arg_ptr, first_part);
585 11567 : result = do_make_filename (1, first_part, arg_ptr);
586 11567 : va_end (arg_ptr);
587 11567 : return result;
588 : }
589 :
590 : /* Construct a filename from the NULL terminated list of parts. Tilde
591 : expansion is done for the first argument. This function may return
592 : NULL on error. */
593 : char *
594 644 : make_filename_try (const char *first_part, ... )
595 : {
596 : va_list arg_ptr;
597 : char *result;
598 :
599 644 : va_start (arg_ptr, first_part);
600 644 : result = do_make_filename (0, first_part, arg_ptr);
601 644 : va_end (arg_ptr);
602 644 : return result;
603 : }
604 :
605 : /* Construct an absolute filename from the NULL terminated list of
606 : parts. Tilde expansion is done for the first argument. This
607 : function terminates the process on memory shortage. */
608 : char *
609 4849 : make_absfilename (const char *first_part, ... )
610 : {
611 : va_list arg_ptr;
612 : char *result;
613 :
614 4849 : va_start (arg_ptr, first_part);
615 4849 : result = do_make_filename (3, first_part, arg_ptr);
616 4849 : va_end (arg_ptr);
617 4849 : return result;
618 : }
619 :
620 : /* Construct an absolute filename from the NULL terminated list of
621 : parts. Tilde expansion is done for the first argument. This
622 : function may return NULL on error. */
623 : char *
624 108 : make_absfilename_try (const char *first_part, ... )
625 : {
626 : va_list arg_ptr;
627 : char *result;
628 :
629 108 : va_start (arg_ptr, first_part);
630 108 : result = do_make_filename (2, first_part, arg_ptr);
631 108 : va_end (arg_ptr);
632 108 : return result;
633 : }
634 :
635 :
636 :
637 : /* Compare whether the filenames are identical. This is a
638 : special version of strcmp() taking the semantics of filenames in
639 : account. Note that this function works only on the supplied names
640 : without considering any context like the current directory. See
641 : also same_file_p(). */
642 : int
643 1607 : compare_filenames (const char *a, const char *b)
644 : {
645 : #ifdef HAVE_DOSISH_SYSTEM
646 : for ( ; *a && *b; a++, b++ )
647 : {
648 : if (*a != *b
649 : && (toupper (*(const unsigned char*)a)
650 : != toupper (*(const unsigned char*)b) )
651 : && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
652 : break;
653 : }
654 : if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))
655 : return 0;
656 : else
657 : return (toupper (*(const unsigned char*)a)
658 : - toupper (*(const unsigned char*)b));
659 : #else
660 1607 : return strcmp(a,b);
661 : #endif
662 : }
663 :
664 :
665 : /* Convert a base-10 number in STRING into a 64 bit unsigned int
666 : * value. Leading white spaces are skipped but no error checking is
667 : * done. Thus it is similar to atoi(). */
668 : uint64_t
669 0 : string_to_u64 (const char *string)
670 : {
671 0 : uint64_t val = 0;
672 :
673 0 : while (spacep (string))
674 0 : string++;
675 0 : for (; digitp (string); string++)
676 : {
677 0 : val *= 10;
678 0 : val += *string - '0';
679 : }
680 0 : return val;
681 : }
682 :
683 :
684 : /* Convert 2 hex characters at S to a byte value. Return this value
685 : or -1 if there is an error. */
686 : int
687 3880 : hextobyte (const char *s)
688 : {
689 : int c;
690 :
691 3880 : if ( *s >= '0' && *s <= '9' )
692 2466 : c = 16 * (*s - '0');
693 1414 : else if ( *s >= 'A' && *s <= 'F' )
694 1414 : c = 16 * (10 + *s - 'A');
695 0 : else if ( *s >= 'a' && *s <= 'f' )
696 0 : c = 16 * (10 + *s - 'a');
697 : else
698 0 : return -1;
699 3880 : s++;
700 3880 : if ( *s >= '0' && *s <= '9' )
701 2415 : c += *s - '0';
702 1465 : else if ( *s >= 'A' && *s <= 'F' )
703 1465 : c += 10 + *s - 'A';
704 0 : else if ( *s >= 'a' && *s <= 'f' )
705 0 : c += 10 + *s - 'a';
706 : else
707 0 : return -1;
708 3880 : return c;
709 : }
710 :
711 : /* Given a string containing an UTF-8 encoded text, return the number
712 : of characters in this string. It differs from strlen in that it
713 : only counts complete UTF-8 characters. SIZE is the maximum length
714 : of the string in bytes. If SIZE is -1, then a NUL character is
715 : taken to be the end of the string. Note, that this function does
716 : not take combined characters into account. */
717 : size_t
718 1278 : utf8_charcount (const char *s, int len)
719 : {
720 : size_t n;
721 :
722 1278 : if (len == 0)
723 70 : return 0;
724 :
725 40919 : for (n=0; *s; s++)
726 : {
727 40914 : if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
728 40914 : n++;
729 :
730 40914 : if (len != -1)
731 : {
732 40875 : len --;
733 40875 : if (len == 0)
734 1203 : break;
735 : }
736 : }
737 :
738 1208 : return n;
739 : }
740 :
741 :
742 : /****************************************************
743 : ********** W32 specific functions ****************
744 : ****************************************************/
745 :
746 : #ifdef HAVE_W32_SYSTEM
747 : const char *
748 : w32_strerror (int ec)
749 : {
750 : static char strerr[256];
751 :
752 : if (ec == -1)
753 : ec = (int)GetLastError ();
754 : #ifdef HAVE_W32CE_SYSTEM
755 : /* There is only a wchar_t FormatMessage. It does not make much
756 : sense to play the conversion game; we print only the code. */
757 : snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ());
758 : #else
759 : FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
760 : MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
761 : strerr, DIM (strerr)-1, NULL);
762 : #endif
763 : return strerr;
764 : }
765 : #endif /*HAVE_W32_SYSTEM*/
766 :
767 :
768 : /****************************************************
769 : ******** Locale insensitive ctype functions ********
770 : ****************************************************/
771 : /* FIXME: replace them by a table lookup and macros */
772 : int
773 0 : ascii_isupper (int c)
774 : {
775 0 : return c >= 'A' && c <= 'Z';
776 : }
777 :
778 : int
779 0 : ascii_islower (int c)
780 : {
781 0 : return c >= 'a' && c <= 'z';
782 : }
783 :
784 : int
785 825552 : ascii_toupper (int c)
786 : {
787 825552 : if (c >= 'a' && c <= 'z')
788 624011 : c &= ~0x20;
789 825552 : return c;
790 : }
791 :
792 : int
793 3245 : ascii_tolower (int c)
794 : {
795 3245 : if (c >= 'A' && c <= 'Z')
796 372 : c |= 0x20;
797 3245 : return c;
798 : }
799 :
800 : /* Lowercase all ASCII characters in S. */
801 : char *
802 627 : ascii_strlwr (char *s)
803 : {
804 627 : char *p = s;
805 :
806 9403 : for (p=s; *p; p++ )
807 8776 : if (isascii (*p) && *p >= 'A' && *p <= 'Z')
808 203 : *p |= 0x20;
809 :
810 627 : return s;
811 : }
812 :
813 : int
814 8034 : ascii_strcasecmp( const char *a, const char *b )
815 : {
816 8034 : if (a == b)
817 0 : return 0;
818 :
819 35367 : for (; *a && *b; a++, b++) {
820 33398 : if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
821 6065 : break;
822 : }
823 8034 : return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
824 : }
825 :
826 : int
827 151 : ascii_strncasecmp (const char *a, const char *b, size_t n)
828 : {
829 151 : const unsigned char *p1 = (const unsigned char *)a;
830 151 : const unsigned char *p2 = (const unsigned char *)b;
831 : unsigned char c1, c2;
832 :
833 151 : if (p1 == p2 || !n )
834 0 : return 0;
835 :
836 : do
837 : {
838 1618 : c1 = ascii_tolower (*p1);
839 1618 : c2 = ascii_tolower (*p2);
840 :
841 1618 : if ( !--n || c1 == '\0')
842 : break;
843 :
844 1582 : ++p1;
845 1582 : ++p2;
846 : }
847 1582 : while (c1 == c2);
848 :
849 151 : return c1 - c2;
850 : }
851 :
852 :
853 : int
854 198254 : ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
855 : {
856 198254 : const char *a = a_arg;
857 198254 : const char *b = b_arg;
858 :
859 198254 : if (a == b)
860 0 : return 0;
861 217241 : for ( ; n; n--, a++, b++ )
862 : {
863 217024 : if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
864 198037 : return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
865 : }
866 217 : return 0;
867 : }
868 :
869 : int
870 0 : ascii_strcmp( const char *a, const char *b )
871 : {
872 0 : if (a == b)
873 0 : return 0;
874 :
875 0 : for (; *a && *b; a++, b++) {
876 0 : if (*a != *b )
877 0 : break;
878 : }
879 0 : return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
880 : }
881 :
882 :
883 : void *
884 8577 : ascii_memcasemem (const void *haystack, size_t nhaystack,
885 : const void *needle, size_t nneedle)
886 : {
887 :
888 8577 : if (!nneedle)
889 0 : return (void*)haystack; /* finding an empty needle is really easy */
890 8577 : if (nneedle <= nhaystack)
891 : {
892 8225 : const char *a = haystack;
893 8225 : const char *b = a + nhaystack - nneedle;
894 :
895 204544 : for (; a <= b; a++)
896 : {
897 196536 : if ( !ascii_memcasecmp (a, needle, nneedle) )
898 217 : return (void *)a;
899 : }
900 : }
901 8360 : return NULL;
902 : }
903 :
904 : /*********************************************
905 : ********** missing string functions *********
906 : *********************************************/
907 :
908 : #ifndef HAVE_STPCPY
909 : char *
910 : stpcpy(char *a,const char *b)
911 : {
912 : while( *b )
913 : *a++ = *b++;
914 : *a = 0;
915 :
916 : return (char*)a;
917 : }
918 : #endif
919 :
920 : #ifndef HAVE_STRPBRK
921 : /* Find the first occurrence in S of any character in ACCEPT.
922 : Code taken from glibc-2.6/string/strpbrk.c (LGPLv2.1+) and modified. */
923 : char *
924 : strpbrk (const char *s, const char *accept)
925 : {
926 : while (*s != '\0')
927 : {
928 : const char *a = accept;
929 : while (*a != '\0')
930 : if (*a++ == *s)
931 : return (char *) s;
932 : ++s;
933 : }
934 :
935 : return NULL;
936 : }
937 : #endif /*!HAVE_STRPBRK*/
938 :
939 :
940 : #ifndef HAVE_STRSEP
941 : /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
942 : char *
943 : strsep (char **stringp, const char *delim)
944 : {
945 : char *begin, *end;
946 :
947 : begin = *stringp;
948 : if (begin == NULL)
949 : return NULL;
950 :
951 : /* A frequent case is when the delimiter string contains only one
952 : character. Here we don't need to call the expensive 'strpbrk'
953 : function and instead work using 'strchr'. */
954 : if (delim[0] == '\0' || delim[1] == '\0')
955 : {
956 : char ch = delim[0];
957 :
958 : if (ch == '\0')
959 : end = NULL;
960 : else
961 : {
962 : if (*begin == ch)
963 : end = begin;
964 : else if (*begin == '\0')
965 : end = NULL;
966 : else
967 : end = strchr (begin + 1, ch);
968 : }
969 : }
970 : else
971 : /* Find the end of the token. */
972 : end = strpbrk (begin, delim);
973 :
974 : if (end)
975 : {
976 : /* Terminate the token and set *STRINGP past NUL character. */
977 : *end++ = '\0';
978 : *stringp = end;
979 : }
980 : else
981 : /* No more delimiters; this is the last token. */
982 : *stringp = NULL;
983 :
984 : return begin;
985 : }
986 : #endif /*HAVE_STRSEP*/
987 :
988 :
989 : #ifndef HAVE_STRLWR
990 : char *
991 28 : strlwr(char *s)
992 : {
993 : char *p;
994 596 : for(p=s; *p; p++ )
995 568 : *p = tolower(*p);
996 28 : return s;
997 : }
998 : #endif
999 :
1000 :
1001 : #ifndef HAVE_STRCASECMP
1002 : int
1003 : strcasecmp( const char *a, const char *b )
1004 : {
1005 : for( ; *a && *b; a++, b++ ) {
1006 : if( *a != *b && toupper(*a) != toupper(*b) )
1007 : break;
1008 : }
1009 : return *(const byte*)a - *(const byte*)b;
1010 : }
1011 : #endif
1012 :
1013 :
1014 : /****************
1015 : * mingw32/cpd has a memicmp()
1016 : */
1017 : #ifndef HAVE_MEMICMP
1018 : int
1019 2 : memicmp( const char *a, const char *b, size_t n )
1020 : {
1021 32 : for( ; n; n--, a++, b++ )
1022 30 : if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
1023 0 : return *(const byte *)a - *(const byte*)b;
1024 2 : return 0;
1025 : }
1026 : #endif
1027 :
1028 :
1029 : #ifndef HAVE_MEMRCHR
1030 : void *
1031 : memrchr (const void *buffer, int c, size_t n)
1032 : {
1033 : const unsigned char *p = buffer;
1034 :
1035 : for (p += n; n ; n--)
1036 : if (*--p == c)
1037 : return (void *)p;
1038 : return NULL;
1039 : }
1040 : #endif /*HAVE_MEMRCHR*/
1041 :
1042 :
1043 : /* Percent-escape the string STR by replacing colons with '%3a'. If
1044 : EXTRA is not NULL all characters in EXTRA are also escaped. */
1045 : static char *
1046 24 : do_percent_escape (const char *str, const char *extra, int die)
1047 : {
1048 : int i, j;
1049 : char *ptr;
1050 :
1051 24 : if (!str)
1052 1 : return NULL;
1053 :
1054 179 : for (i=j=0; str[i]; i++)
1055 156 : if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
1056 40 : j++;
1057 23 : if (die)
1058 21 : ptr = xmalloc (i + 2 * j + 1);
1059 : else
1060 : {
1061 2 : ptr = xtrymalloc (i + 2 * j + 1);
1062 2 : if (!ptr)
1063 0 : return NULL;
1064 : }
1065 23 : i = 0;
1066 202 : while (*str)
1067 : {
1068 156 : if (*str == ':')
1069 : {
1070 20 : ptr[i++] = '%';
1071 20 : ptr[i++] = '3';
1072 20 : ptr[i++] = 'a';
1073 : }
1074 136 : else if (*str == '%')
1075 : {
1076 15 : ptr[i++] = '%';
1077 15 : ptr[i++] = '2';
1078 15 : ptr[i++] = '5';
1079 : }
1080 121 : else if (extra && strchr (extra, *str))
1081 : {
1082 5 : ptr[i++] = '%';
1083 5 : ptr[i++] = tohex_lower ((*str>>4)&15);
1084 5 : ptr[i++] = tohex_lower (*str&15);
1085 : }
1086 : else
1087 116 : ptr[i++] = *str;
1088 156 : str++;
1089 : }
1090 23 : ptr[i] = '\0';
1091 :
1092 23 : return ptr;
1093 : }
1094 :
1095 : /* Percent-escape the string STR by replacing colons with '%3a'. If
1096 : EXTRA is not NULL all characters in EXTRA are also escaped. This
1097 : function terminates the process on memory shortage. */
1098 : char *
1099 22 : percent_escape (const char *str, const char *extra)
1100 : {
1101 22 : return do_percent_escape (str, extra, 1);
1102 : }
1103 :
1104 : /* Same as percent_escape but return NULL instead of exiting on memory
1105 : error. */
1106 : char *
1107 2 : try_percent_escape (const char *str, const char *extra)
1108 : {
1109 2 : return do_percent_escape (str, extra, 0);
1110 : }
1111 :
1112 :
1113 :
1114 : static char *
1115 2187 : do_strconcat (const char *s1, va_list arg_ptr)
1116 : {
1117 : const char *argv[48];
1118 : size_t argc;
1119 : size_t needed;
1120 : char *buffer, *p;
1121 :
1122 2187 : argc = 0;
1123 2187 : argv[argc++] = s1;
1124 2187 : needed = strlen (s1);
1125 8883 : while (((argv[argc] = va_arg (arg_ptr, const char *))))
1126 : {
1127 4511 : needed += strlen (argv[argc]);
1128 4511 : if (argc >= DIM (argv)-1)
1129 : {
1130 2 : gpg_err_set_errno (EINVAL);
1131 2 : return NULL;
1132 : }
1133 4509 : argc++;
1134 : }
1135 2185 : needed++;
1136 2185 : buffer = xtrymalloc (needed);
1137 2185 : if (buffer)
1138 : {
1139 8787 : for (p = buffer, argc=0; argv[argc]; argc++)
1140 6602 : p = stpcpy (p, argv[argc]);
1141 : }
1142 2185 : return buffer;
1143 : }
1144 :
1145 :
1146 : /* Concatenate the string S1 with all the following strings up to a
1147 : NULL. Returns a malloced buffer with the new string or NULL on a
1148 : malloc error or if too many arguments are given. */
1149 : char *
1150 2134 : strconcat (const char *s1, ...)
1151 : {
1152 : va_list arg_ptr;
1153 : char *result;
1154 :
1155 2134 : if (!s1)
1156 1 : result = xtrystrdup ("");
1157 : else
1158 : {
1159 2133 : va_start (arg_ptr, s1);
1160 2133 : result = do_strconcat (s1, arg_ptr);
1161 2133 : va_end (arg_ptr);
1162 : }
1163 2134 : return result;
1164 : }
1165 :
1166 : /* Same as strconcat but terminate the process with an error message
1167 : if something goes wrong. */
1168 : char *
1169 55 : xstrconcat (const char *s1, ...)
1170 : {
1171 : va_list arg_ptr;
1172 : char *result;
1173 :
1174 55 : if (!s1)
1175 1 : result = xstrdup ("");
1176 : else
1177 : {
1178 54 : va_start (arg_ptr, s1);
1179 54 : result = do_strconcat (s1, arg_ptr);
1180 54 : va_end (arg_ptr);
1181 : }
1182 55 : if (!result)
1183 : {
1184 0 : if (errno == EINVAL)
1185 0 : fputs ("\nfatal: too many args for xstrconcat\n", stderr);
1186 : else
1187 0 : fputs ("\nfatal: out of memory\n", stderr);
1188 0 : exit (2);
1189 : }
1190 55 : return result;
1191 : }
1192 :
1193 : /* Split a string into fields at DELIM. REPLACEMENT is the character
1194 : to replace the delimiter with (normally: '\0' so that each field is
1195 : NUL terminated). The caller is responsible for freeing the result.
1196 : Note: this function modifies STRING! If you need the original
1197 : value, then you should pass a copy to this function.
1198 :
1199 : If malloc fails, this function returns NULL. */
1200 : char **
1201 3 : strsplit (char *string, char delim, char replacement, int *count)
1202 : {
1203 3 : int fields = 1;
1204 : char *t;
1205 : char **result;
1206 :
1207 : /* First, count the number of fields. */
1208 15 : for (t = strchr (string, delim); t; t = strchr (t + 1, delim))
1209 12 : fields ++;
1210 :
1211 3 : result = xtrycalloc ((fields + 1), sizeof (*result));
1212 3 : if (! result)
1213 0 : return NULL;
1214 :
1215 3 : result[0] = string;
1216 3 : fields = 1;
1217 15 : for (t = strchr (string, delim); t; t = strchr (t + 1, delim))
1218 : {
1219 12 : result[fields ++] = t + 1;
1220 12 : *t = replacement;
1221 : }
1222 :
1223 3 : if (count)
1224 3 : *count = fields;
1225 :
1226 3 : return result;
1227 : }
1228 :
1229 :
1230 : /* Tokenize STRING using the set of delimiters in DELIM. Leading
1231 : * spaces and tabs are removed from all tokens. The caller must xfree
1232 : * the result.
1233 : *
1234 : * Returns: A malloced and NULL delimited array with the tokens. On
1235 : * memory error NULL is returned and ERRNO is set.
1236 : */
1237 : char **
1238 25 : strtokenize (const char *string, const char *delim)
1239 : {
1240 : const char *s;
1241 : size_t fields;
1242 : size_t bytes, n;
1243 : char *buffer;
1244 : char *p, *px, *pend;
1245 : char **result;
1246 :
1247 : /* Count the number of fields. */
1248 67 : for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
1249 42 : fields++;
1250 25 : fields++; /* Add one for the terminating NULL. */
1251 :
1252 : /* Allocate an array for all fields, a terminating NULL, and space
1253 : for a copy of the string. */
1254 25 : bytes = fields * sizeof *result;
1255 25 : if (bytes / sizeof *result != fields)
1256 : {
1257 0 : gpg_err_set_errno (ENOMEM);
1258 0 : return NULL;
1259 : }
1260 25 : n = strlen (string) + 1;
1261 25 : bytes += n;
1262 25 : if (bytes < n)
1263 : {
1264 0 : gpg_err_set_errno (ENOMEM);
1265 0 : return NULL;
1266 : }
1267 25 : result = xtrymalloc (bytes);
1268 25 : if (!result)
1269 0 : return NULL;
1270 25 : buffer = (char*)(result + fields);
1271 :
1272 : /* Copy and parse the string. */
1273 25 : strcpy (buffer, string);
1274 67 : for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
1275 : {
1276 42 : *pend = 0;
1277 98 : while (spacep (p))
1278 14 : p++;
1279 42 : for (px = pend - 1; px >= p && spacep (px); px--)
1280 0 : *px = 0;
1281 42 : result[n++] = p;
1282 : }
1283 57 : while (spacep (p))
1284 7 : p++;
1285 28 : for (px = p + strlen (p) - 1; px >= p && spacep (px); px--)
1286 3 : *px = 0;
1287 25 : result[n++] = p;
1288 25 : result[n] = NULL;
1289 :
1290 25 : assert ((char*)(result + n + 1) == buffer);
1291 :
1292 25 : return result;
1293 : }
1294 :
1295 :
1296 : /* Split a string into space delimited fields and remove leading and
1297 : * trailing spaces from each field. A pointer to each field is stored
1298 : * in ARRAY. Stop splitting at ARRAYSIZE fields. The function
1299 : * modifies STRING. The number of parsed fields is returned.
1300 : * Example:
1301 : *
1302 : * char *fields[2];
1303 : * if (split_fields (string, fields, DIM (fields)) < 2)
1304 : * return // Not enough args.
1305 : * foo (fields[0]);
1306 : * foo (fields[1]);
1307 : */
1308 : int
1309 65 : split_fields (char *string, char **array, int arraysize)
1310 : {
1311 65 : int n = 0;
1312 : char *p, *pend;
1313 :
1314 65 : for (p = string; *p == ' '; p++)
1315 : ;
1316 : do
1317 : {
1318 436 : if (n == arraysize)
1319 62 : break;
1320 374 : array[n++] = p;
1321 374 : pend = strchr (p, ' ');
1322 374 : if (!pend)
1323 0 : break;
1324 374 : *pend++ = 0;
1325 374 : for (p = pend; *p == ' '; p++)
1326 : ;
1327 : }
1328 374 : while (*p);
1329 :
1330 65 : return n;
1331 : }
1332 :
1333 :
1334 :
1335 : /* Version number parsing. */
1336 :
1337 : /* This function parses the first portion of the version number S and
1338 : stores it in *NUMBER. On success, this function returns a pointer
1339 : into S starting with the first character, which is not part of the
1340 : initial number portion; on failure, NULL is returned. */
1341 : static const char*
1342 3426 : parse_version_number (const char *s, int *number)
1343 : {
1344 3426 : int val = 0;
1345 :
1346 3426 : if (*s == '0' && digitp (s+1))
1347 0 : return NULL; /* Leading zeros are not allowed. */
1348 7914 : for (; digitp (s); s++)
1349 : {
1350 4488 : val *= 10;
1351 4488 : val += *s - '0';
1352 : }
1353 3426 : *number = val;
1354 3426 : return val < 0 ? NULL : s;
1355 : }
1356 :
1357 :
1358 : /* This function breaks up the complete string-representation of the
1359 : version number S, which is of the following struture: <major
1360 : number>.<minor number>[.<micro number>]<patch level>. The major,
1361 : minor, and micro number components will be stored in *MAJOR, *MINOR
1362 : and *MICRO. If MICRO is not given 0 is used instead.
1363 :
1364 : On success, the last component, the patch level, will be returned;
1365 : in failure, NULL will be returned. */
1366 : static const char *
1367 1149 : parse_version_string (const char *s, int *major, int *minor, int *micro)
1368 : {
1369 1149 : s = parse_version_number (s, major);
1370 1149 : if (!s || *s != '.')
1371 6 : return NULL;
1372 1143 : s++;
1373 1143 : s = parse_version_number (s, minor);
1374 1143 : if (!s)
1375 0 : return NULL;
1376 1143 : if (*s == '.')
1377 : {
1378 1134 : s++;
1379 1134 : s = parse_version_number (s, micro);
1380 1134 : if (!s)
1381 0 : return NULL;
1382 : }
1383 : else
1384 9 : *micro = 0;
1385 1143 : return s; /* Patchlevel. */
1386 : }
1387 :
1388 :
1389 : /* Compare the version string MY_VERSION to the version string
1390 : * REQ_VERSION. Returns -1, 0, or 1 if MY_VERSION is found,
1391 : * respectively, to be less than, to match, or be greater than
1392 : * REQ_VERSION. This function works for three and two part version
1393 : * strings; for a two part version string the micro part is assumed to
1394 : * be 0. Patch levels are compared as strings. If a version number
1395 : * is invalid INT_MIN is returned. If REQ_VERSION is given as NULL
1396 : * the function returns 0 if MY_VERSION is parsable version string. */
1397 : int
1398 580 : compare_version_strings (const char *my_version, const char *req_version)
1399 : {
1400 : int my_major, my_minor, my_micro;
1401 : int rq_major, rq_minor, rq_micro;
1402 : const char *my_patch, *rq_patch;
1403 : int result;
1404 :
1405 580 : if (!my_version)
1406 2 : return INT_MIN;
1407 :
1408 578 : my_patch = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
1409 578 : if (!my_patch)
1410 4 : return INT_MIN;
1411 574 : if (!req_version)
1412 3 : return 0; /* MY_VERSION can be parsed. */
1413 571 : rq_patch = parse_version_string (req_version, &rq_major, &rq_minor,&rq_micro);
1414 571 : if (!rq_patch)
1415 2 : return INT_MIN;
1416 :
1417 569 : if (my_major == rq_major)
1418 : {
1419 568 : if (my_minor == rq_minor)
1420 : {
1421 558 : if (my_micro == rq_micro)
1422 549 : result = strcmp (my_patch, rq_patch);
1423 : else
1424 9 : result = my_micro - rq_micro;
1425 : }
1426 : else
1427 10 : result = my_minor - rq_minor;
1428 : }
1429 : else
1430 1 : result = my_major - rq_major;
1431 :
1432 569 : return !result? 0 : result < 0 ? -1 : 1;
1433 : }
1434 :
1435 :
1436 :
1437 : /* Format a string so that it fits within about TARGET_COLS columns.
1438 : If IN_PLACE is 0, then TEXT is copied to a new buffer, which is
1439 : returned. Otherwise, TEXT is modified in place and returned.
1440 : Normally, target_cols will be 72 and max_cols is 80. */
1441 : char *
1442 54 : format_text (char *text, int in_place, int target_cols, int max_cols)
1443 : {
1444 54 : const int do_debug = 0;
1445 :
1446 : /* The character under consideration. */
1447 : char *p;
1448 : /* The start of the current line. */
1449 : char *line;
1450 : /* The last space that we saw. */
1451 54 : char *last_space = NULL;
1452 54 : int last_space_cols = 0;
1453 54 : int copied_last_space = 0;
1454 :
1455 54 : if (! in_place)
1456 54 : text = xstrdup (text);
1457 :
1458 54 : p = line = text;
1459 : while (1)
1460 : {
1461 : /* The number of columns including any trailing space. */
1462 : int cols;
1463 :
1464 1354 : p = p + strcspn (p, "\n ");
1465 1354 : if (! p)
1466 : /* P now points to the NUL character. */
1467 0 : p = &text[strlen (text)];
1468 :
1469 1354 : if (*p == '\n')
1470 : /* Pass through any newlines. */
1471 : {
1472 81 : p ++;
1473 81 : line = p;
1474 81 : last_space = NULL;
1475 81 : last_space_cols = 0;
1476 81 : copied_last_space = 1;
1477 81 : continue;
1478 : }
1479 :
1480 : /* Have a space or a NUL. Note: we don't count the trailing
1481 : space. */
1482 1273 : cols = utf8_charcount (line, (uintptr_t) p - (uintptr_t) line);
1483 1273 : if (cols < target_cols)
1484 : {
1485 1198 : if (! *p)
1486 : /* Nothing left to break. */
1487 54 : break;
1488 :
1489 1144 : last_space = p;
1490 1144 : last_space_cols = cols;
1491 1144 : p ++;
1492 : /* Skip any immediately following spaces. If we break:
1493 : "... foo bar ..." between "foo" and "bar" then we want:
1494 : "... foo\nbar ...", which means that the left space has
1495 : to be the first space after foo, not the last space
1496 : before bar. */
1497 2351 : while (*p == ' ')
1498 63 : p ++;
1499 : }
1500 : else
1501 : {
1502 : int cols_with_left_space;
1503 : int cols_with_right_space;
1504 : int left_penalty;
1505 : int right_penalty;
1506 :
1507 75 : cols_with_left_space = last_space_cols;
1508 75 : cols_with_right_space = cols;
1509 :
1510 75 : if (do_debug)
1511 0 : log_debug ("Breaking: '%.*s'\n",
1512 0 : (int) ((uintptr_t) p - (uintptr_t) line), line);
1513 :
1514 : /* The number of columns away from TARGET_COLS. We prefer
1515 : to underflow than to overflow. */
1516 75 : left_penalty = target_cols - cols_with_left_space;
1517 75 : right_penalty = 2 * (cols_with_right_space - target_cols);
1518 :
1519 75 : if (cols_with_right_space > max_cols)
1520 : /* Add a large penalty for each column that exceeds
1521 : max_cols. */
1522 1 : right_penalty += 4 * (cols_with_right_space - max_cols);
1523 :
1524 75 : if (do_debug)
1525 0 : log_debug ("Left space => %d cols (penalty: %d); right space => %d cols (penalty: %d)\n",
1526 : cols_with_left_space, left_penalty,
1527 : cols_with_right_space, right_penalty);
1528 75 : if (last_space_cols && left_penalty <= right_penalty)
1529 : /* Prefer the left space. */
1530 : {
1531 37 : if (do_debug)
1532 0 : log_debug ("Breaking at left space.\n");
1533 37 : p = last_space;
1534 : }
1535 : else
1536 : {
1537 38 : if (do_debug)
1538 0 : log_debug ("Breaking at right space.\n");
1539 : }
1540 :
1541 75 : if (! *p)
1542 0 : break;
1543 :
1544 75 : *p = '\n';
1545 75 : p ++;
1546 75 : if (*p == ' ')
1547 : {
1548 : int spaces;
1549 5 : for (spaces = 1; p[spaces] == ' '; spaces ++)
1550 : ;
1551 5 : memmove (p, &p[spaces], strlen (&p[spaces]) + 1);
1552 : }
1553 75 : line = p;
1554 75 : last_space = NULL;
1555 75 : last_space_cols = 0;
1556 75 : copied_last_space = 0;
1557 : }
1558 1300 : }
1559 :
1560 : /* Chop off any trailing space. */
1561 54 : trim_trailing_chars (text, strlen (text), " ");
1562 : /* If we inserted the trailing newline, then remove it. */
1563 54 : if (! copied_last_space && *text && text[strlen (text) - 1] == '\n')
1564 0 : text[strlen (text) - 1] = '\0';
1565 :
1566 54 : return text;
1567 : }
|