Don't grep directories, since that breaks on NFS-mounted file systems.
[deliverable/binutils-gdb.git] / gdb / cplus-dem.c
CommitLineData
dd3b648e
RP
1/* Demangler for GNU C++
2 Copyright (C) 1989 Free Software Foundation, Inc.
3 written by James Clark (jjc@jclark.uucp)
4
99a7de40
JG
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
dd3b648e
RP
18
19/* This is for g++ 1.36.1 (November 6 version). It will probably
20 require changes for any other version.
21
55838914
JK
22 Modified for g++ 1.36.2 (November 18 version).
23
24 Modified for g++ 1.90.06 (December 31 version). */
dd3b648e
RP
25
26/* This file exports one function
27
28 char *cplus_demangle (const char *name, int mode)
29
30 If NAME is a mangled function name produced by GNU C++, then
31 a pointer to a malloced string giving a C++ representation
32 of the name will be returned; otherwise NULL will be returned.
33 It is the caller's responsibility to free the string which
34 is returned.
35
36 If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
37 Otherwise they are not.
38 If MODE >= 0, parameters are emitted; otherwise not.
39
40 For example,
41
42 cplus_demangle ("foo__1Ai", 0) => "A::foo(int)"
43 cplus_demangle ("foo__1Ai", 1) => "A::foo(int)"
44 cplus_demangle ("foo__1Ai", -1) => "A::foo"
45
46 cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)"
47 cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)"
48 cplus_demangle ("foo__1Afe", -1) => "A::foo"
49
50 This file imports xmalloc and xrealloc, which are like malloc and
51 realloc except that they generate a fatal error if there is no
52 available memory. */
53
54/* define this if names don't start with _ */
55/* #define nounderscore 1 */
56
57#include <stdio.h>
58#include <ctype.h>
59
e1ce8aa5
JK
60/* GDB-specific, FIXME. */
61#include "defs.h"
62#include "param.h"
63
dd3b648e
RP
64#ifdef USG
65#include <memory.h>
66#include <string.h>
67#else
68#include <strings.h>
69#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
70#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
71#define strchr index
72#define strrchr rindex
73#endif
74
8ffd75c8
JG
75/* This is '$' on systems where the assembler can deal with that.
76 Where the assembler can't, it's '.' (but on many systems '.' is
77 used for other things). */
78#if !defined (CPLUS_MARKER)
79#define CPLUS_MARKER '$'
80#endif
81
dd3b648e
RP
82#ifndef __STDC__
83#define const
84#endif
85
86#ifdef __STDC__
87extern char *cplus_demangle (const char *type, int mode);
88#else
89extern char *cplus_demangle ();
90#endif
91
92#ifdef __STDC__
2cb3be2c
JK
93/* GDB prototypes these as void* in defs.h, so we better too, at least
94 as long as we're including defs.h. */
95extern void *xmalloc (int);
96extern void *xrealloc (char *, int);
d11c44f1 97extern void free (void *);
dd3b648e
RP
98#else
99extern char *xmalloc ();
100extern char *xrealloc ();
101extern void free ();
102#endif
103
104static char **typevec = 0;
105static int ntypes = 0;
106static int typevec_size = 0;
107
ef98d5ac 108const static struct optable {
dd3b648e
RP
109 const char *in;
110 const char *out;
111} optable[] = {
55838914
JK
112 "nw", " new", /* new (1.92) */
113 "dl", " delete", /* new (1.92) */
114 "new", " new", /* old (1.91, and 1.x) */
115 "delete", " delete", /* old (1.91, and 1.x) */
dd3b648e
RP
116 "ne", "!=",
117 "eq", "==",
118 "ge", ">=",
119 "gt", ">",
120 "le", "<=",
121 "lt", "<",
122 "plus", "+",
123 "minus", "-",
124 "mult", "*",
125 "convert", "+", /* unary + */
126 "negate", "-", /* unary - */
127 "trunc_mod", "%",
128 "trunc_div", "/",
129 "truth_andif", "&&",
130 "truth_orif", "||",
131 "truth_not", "!",
132 "postincrement", "++",
133 "postdecrement", "--",
134 "bit_ior", "|",
135 "bit_xor", "^",
136 "bit_and", "&",
137 "bit_not", "~",
138 "call", "()",
139 "cond", "?:",
140 "alshift", "<<",
141 "arshift", ">>",
142 "component", "->",
143 "indirect", "*",
144 "method_call", "->()",
145 "addr", "&", /* unary & */
146 "array", "[]",
55838914 147 "compound", ",",
dd3b648e
RP
148 "nop", "", /* for operator= */
149};
150
151/* Beware: these aren't '\0' terminated. */
152
ef98d5ac 153typedef struct string {
dd3b648e
RP
154 char *b; /* pointer to start of string */
155 char *p; /* pointer after last character */
156 char *e; /* pointer after end of allocated space */
157} string;
158
159#ifdef __STDC__
160static void string_need (string *s, int n);
161static void string_delete (string *s);
162static void string_init (string *s);
163static void string_clear (string *s);
164static int string_empty (string *s);
165static void string_append (string *p, const char *s);
166static void string_appends (string *p, string *s);
167static void string_appendn (string *p, const char *s, int n);
168static void string_prepend (string *p, const char *s);
169#if 0
170static void string_prepends (string *p, string *s);
171#endif
172static void string_prependn (string *p, const char *s, int n);
173static int get_count (const char **type, int *count);
174static int do_args (const char **type, string *decl, int arg_mode);
175static int do_type (const char **type, string *result, int arg_mode);
176static int do_arg (const char **type, string *result, int arg_mode);
177static void munge_function_name (string *name, int arg_mode);
178static void remember_type (const char *type, int len);
179#else
180static void string_need ();
181static void string_delete ();
182static void string_init ();
183static void string_clear ();
184static int string_empty ();
185static void string_append ();
186static void string_appends ();
187static void string_appendn ();
188static void string_prepend ();
189#if 0
190static void string_prepends ();
191#endif
192static void string_prependn ();
193static int get_count ();
194static int do_args ();
195static int do_type ();
196static int do_arg ();
197static int do_args ();
198static void munge_function_name ();
199static void remember_type ();
200#endif
201
55838914 202/* Takes operator name as e.g. "++" and returns mangled
e1ce8aa5 203 operator name (e.g. "postincrement_expr"), or NULL if not found. */
55838914
JK
204char *
205cplus_mangle_opname (opname)
206 char *opname;
207{
208 int i, len = strlen (opname);
55838914
JK
209
210 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
211 {
212 if (strlen (optable[i].out) == len
213 && memcmp (optable[i].out, opname, len) == 0)
e1ce8aa5 214 return (char *)optable[i].in;
55838914 215 }
55838914
JK
216 return 0;
217}
218
dd3b648e
RP
219char *
220cplus_demangle (type, arg_mode)
221 const char *type;
222 int arg_mode;
223{
224 string decl;
225 int n;
226 int success = 0;
227 int constructor = 0;
228 int const_flag = 0;
229 int i;
230 const char *p;
231#ifndef LONGERNAMES
232 const char *premangle;
233#endif
234
235# define print_ansi_qualifiers (arg_mode > 0)
236# define print_arg_types (arg_mode >= 0)
237
238 if (type == NULL || *type == '\0')
239 return NULL;
240#ifndef nounderscore
241 if (*type++ != '_')
242 return NULL;
243#endif
244 p = type;
245 while (*p != '\0' && !(*p == '_' && p[1] == '_'))
246 p++;
247 if (*p == '\0')
248 {
249 /* destructor */
f88e7af8 250 if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
dd3b648e 251 {
61a7292f 252 char *tem = (char *) xmalloc ((strlen (type) - 3)*2 + 3 + 2 + 1);
dd3b648e
RP
253 strcpy (tem, type + 3);
254 strcat (tem, "::~");
255 strcat (tem, type + 3);
256 strcat (tem, "()");
257 return tem;
258 }
259 /* static data member */
f88e7af8 260 if (*type != '_' && (p = strchr (type, CPLUS_MARKER)) != NULL)
dd3b648e 261 {
61a7292f 262 char *tem = (char *) xmalloc (strlen (type) + 2);
dd3b648e
RP
263 memcpy (tem, type, p - type);
264 strcpy (tem + (p - type), "::");
265 strcpy (tem + (p - type) + 2, p + 1);
266 return tem;
267 }
268 /* virtual table "_vt$" */
f88e7af8 269 if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
dd3b648e 270 {
61a7292f 271 char *tem = (char *) xmalloc (strlen (type + 4) + 14 + 1);
dd3b648e
RP
272 strcpy (tem, type + 4);
273 strcat (tem, " virtual table");
274 return tem;
275 }
276 return NULL;
277 }
278
279 string_init (&decl);
280
281 if (p == type)
282 {
283 if (!isdigit (p[2]))
284 {
285 string_delete (&decl);
286 return NULL;
287 }
288 constructor = 1;
289 }
290 else
291 {
292 string_appendn (&decl, type, p - type);
293 munge_function_name (&decl, arg_mode);
294 }
295 p += 2;
296
297#ifndef LONGERNAMES
298 premangle = p;
299#endif
300 switch (*p)
301 {
302 case 'C':
303 /* a const member function */
304 if (!isdigit (p[1]))
305 {
306 string_delete (&decl);
307 return NULL;
308 }
309 p += 1;
310 const_flag = 1;
311 /* fall through */
312 case '0':
313 case '1':
314 case '2':
315 case '3':
316 case '4':
317 case '5':
318 case '6':
319 case '7':
320 case '8':
321 case '9':
322 n = 0;
323 do
324 {
325 n *= 10;
326 n += *p - '0';
327 p += 1;
328 }
329 while (isdigit (*p));
330 if (strlen (p) < n)
331 {
332 string_delete (&decl);
333 return NULL;
334 }
335 if (constructor)
336 {
337 string_appendn (&decl, p, n);
338 string_append (&decl, "::");
339 string_appendn (&decl, p, n);
340 }
341 else
342 {
343 string_prepend (&decl, "::");
344 string_prependn (&decl, p, n);
345 }
346 p += n;
347#ifndef LONGERNAMES
348 remember_type (premangle, p - premangle);
349#endif
350 success = do_args (&p, &decl, arg_mode);
351 if (const_flag && print_arg_types)
352 string_append (&decl, " const");
353 break;
354 case 'F':
355 p += 1;
356 success = do_args (&p, &decl, arg_mode);
357 break;
358 }
359
360 for (i = 0; i < ntypes; i++)
361 if (typevec[i] != NULL)
362 free (typevec[i]);
363 ntypes = 0;
364 if (typevec != NULL)
365 {
366 free ((char *)typevec);
367 typevec = NULL;
368 typevec_size = 0;
369 }
370
371 if (success)
372 {
373 string_appendn (&decl, "", 1);
374 return decl.b;
375 }
376 else
377 {
378 string_delete (&decl);
379 return NULL;
380 }
381}
382
383static int
384get_count (type, count)
385 const char **type;
386 int *count;
387{
388 if (!isdigit (**type))
389 return 0;
390 *count = **type - '0';
391 *type += 1;
392 /* see flush_repeats in cplus-method.c */
393 if (isdigit (**type))
394 {
395 const char *p = *type;
396 int n = *count;
397 do
398 {
399 n *= 10;
400 n += *p - '0';
401 p += 1;
402 }
403 while (isdigit (*p));
404 if (*p == '_')
405 {
406 *type = p + 1;
407 *count = n;
408 }
409 }
410 return 1;
411}
412
413/* result will be initialised here; it will be freed on failure */
414
415static int
416do_type (type, result, arg_mode)
417 const char **type;
418 string *result;
419 int arg_mode;
420{
421 int n;
422 int done;
423 int non_empty = 0;
424 int success;
425 string decl;
426 const char *remembered_type;
427
428 string_init (&decl);
429 string_init (result);
430
431 done = 0;
432 success = 1;
433 while (success && !done)
434 {
435 int member;
436 switch (**type)
437 {
55838914
JK
438 case 'Q':
439 n = (*type)[1] - '0';
440 if (n < 0 || n > 9)
441 success = 0;
442 *type += 2;
443 while (n-- > 0)
e1ce8aa5 444 do_type (type, result, arg_mode);
55838914
JK
445 break;
446
dd3b648e
RP
447 case 'P':
448 *type += 1;
449 string_prepend (&decl, "*");
450 break;
451
452 case 'R':
453 *type += 1;
454 string_prepend (&decl, "&");
455 break;
456
457 case 'T':
458 *type += 1;
459 if (!get_count (type, &n) || n >= ntypes)
460 success = 0;
461 else
462 {
463 remembered_type = typevec[n];
464 type = &remembered_type;
465 }
466 break;
467
468 case 'F':
469 *type += 1;
470 if (!string_empty (&decl) && decl.b[0] == '*')
471 {
472 string_prepend (&decl, "(");
473 string_append (&decl, ")");
474 }
475 if (!do_args (type, &decl, arg_mode) || **type != '_')
476 success = 0;
477 else
478 *type += 1;
479 break;
480
481 case 'M':
482 case 'O':
483 {
484 int constp = 0;
485 int volatilep = 0;
486
487 member = **type == 'M';
488 *type += 1;
489 if (!isdigit (**type))
490 {
491 success = 0;
492 break;
493 }
494 n = 0;
495 do
496 {
497 n *= 10;
498 n += **type - '0';
499 *type += 1;
500 }
501 while (isdigit (**type));
502 if (strlen (*type) < n)
503 {
504 success = 0;
505 break;
506 }
507 string_append (&decl, ")");
508 string_prepend (&decl, "::");
509 string_prependn (&decl, *type, n);
510 string_prepend (&decl, "(");
511 *type += n;
512 if (member)
513 {
514 if (**type == 'C')
515 {
516 *type += 1;
517 constp = 1;
518 }
519 if (**type == 'V')
520 {
521 *type += 1;
522 volatilep = 1;
523 }
524 if (*(*type)++ != 'F')
525 {
526 success = 0;
527 break;
528 }
529 }
530 if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
531 {
532 success = 0;
533 break;
534 }
535 *type += 1;
536 if (! print_ansi_qualifiers)
537 break;
538 if (constp)
539 {
540 if (non_empty)
541 string_append (&decl, " ");
542 else
543 non_empty = 1;
544 string_append (&decl, "const");
545 }
546 if (volatilep)
547 {
548 if (non_empty)
549 string_append (&decl, " ");
550 else
551 non_empty = 1;
552 string_append (&decl, "volatile");
553 }
554 break;
555 }
556
557 case 'C':
558 if ((*type)[1] == 'P')
559 {
560 *type += 1;
561 if (print_ansi_qualifiers)
562 {
563 if (!string_empty (&decl))
564 string_prepend (&decl, " ");
565 string_prepend (&decl, "const");
566 }
567 break;
568 }
569
570 /* fall through */
571 default:
572 done = 1;
573 break;
574 }
575 }
576
577 done = 0;
578 non_empty = 0;
579 while (success && !done)
580 {
581 switch (**type)
582 {
583 case 'C':
584 *type += 1;
585 if (print_ansi_qualifiers)
586 {
587 if (non_empty)
588 string_append (result, " ");
589 else
590 non_empty = 1;
591 string_append (result, "const");
592 }
593 break;
594 case 'U':
595 *type += 1;
596 if (non_empty)
597 string_append (result, " ");
598 else
599 non_empty = 1;
600 string_append (result, "unsigned");
601 break;
602 case 'V':
603 *type += 1;
604 if (print_ansi_qualifiers)
605 {
606 if (non_empty)
607 string_append (result, " ");
608 else
609 non_empty = 1;
610 string_append (result, "volatile");
611 }
612 break;
613 default:
614 done = 1;
615 break;
616 }
617 }
618
619 if (success)
620 switch (**type)
621 {
622 case '\0':
623 case '_':
624 break;
625 case 'v':
626 *type += 1;
627 if (non_empty)
628 string_append (result, " ");
629 string_append (result, "void");
630 break;
631 case 'x':
632 *type += 1;
633 if (non_empty)
634 string_append (result, " ");
635 string_append (result, "long long");
636 break;
637 case 'l':
638 *type += 1;
639 if (non_empty)
640 string_append (result, " ");
641 string_append (result, "long");
642 break;
643 case 'i':
644 *type += 1;
645 if (non_empty)
646 string_append (result, " ");
647 string_append (result, "int");
648 break;
649 case 's':
650 *type += 1;
651 if (non_empty)
652 string_append (result, " ");
653 string_append (result, "short");
654 break;
655 case 'c':
656 *type += 1;
657 if (non_empty)
658 string_append (result, " ");
659 string_append (result, "char");
660 break;
661 case 'r':
662 *type += 1;
663 if (non_empty)
664 string_append (result, " ");
665 string_append (result, "long double");
666 break;
667 case 'd':
668 *type += 1;
669 if (non_empty)
670 string_append (result, " ");
671 string_append (result, "double");
672 break;
673 case 'f':
674 *type += 1;
675 if (non_empty)
676 string_append (result, " ");
677 string_append (result, "float");
678 break;
679 case 'G':
680 *type += 1;
681 if (!isdigit (**type))
682 {
683 success = 0;
684 break;
685 }
686 /* fall through */
687 case '0':
688 case '1':
689 case '2':
690 case '3':
691 case '4':
692 case '5':
693 case '6':
694 case '7':
695 case '8':
696 case '9':
697 n = 0;
698 do
699 {
700 n *= 10;
701 n += **type - '0';
702 *type += 1;
703 }
704 while (isdigit (**type));
705 if (strlen (*type) < n)
706 {
707 success = 0;
708 break;
709 }
710 if (non_empty)
711 string_append (result, " ");
712 string_appendn (result, *type, n);
713 *type += n;
714 break;
715 default:
716 success = 0;
717 break;
718 }
719
720 if (success)
721 {
722 if (!string_empty (&decl))
723 {
724 string_append (result, " ");
725 string_appends (result, &decl);
726 }
727 string_delete (&decl);
728 return 1;
729 }
730 else
731 {
732 string_delete (&decl);
733 string_delete (result);
734 return 0;
735 }
736}
737
738/* `result' will be initialised in do_type; it will be freed on failure */
739
740static int
741do_arg (type, result, arg_mode)
742 const char **type;
743 string *result;
744 int arg_mode;
745{
746 const char *start = *type;
747
748 if (!do_type (type, result, arg_mode))
749 return 0;
750 remember_type (start, *type - start);
751 return 1;
752}
753
754static void
755remember_type (start, len)
756 const char *start;
757 int len;
758{
759 char *tem;
760
761 if (ntypes >= typevec_size)
762 {
763 if (typevec_size == 0)
764 {
765 typevec_size = 3;
766 typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
767 }
768 else
769 {
770 typevec_size *= 2;
771 typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
772 }
773 }
774 tem = (char *) xmalloc (len + 1);
775 memcpy (tem, start, len);
776 tem[len] = '\0';
777 typevec[ntypes++] = tem;
778}
779
780/* `decl' must be already initialised, usually non-empty;
781 it won't be freed on failure */
782
783static int
784do_args (type, decl, arg_mode)
785 const char **type;
786 string *decl;
787 int arg_mode;
788{
789 string arg;
790 int need_comma = 0;
791
792 if (print_arg_types)
793 string_append (decl, "(");
794
795 while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
796 {
797 if (**type == 'N')
798 {
799 int r;
800 int t;
801 *type += 1;
802 if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
803 return 0;
804 while (--r >= 0)
805 {
806 const char *tem = typevec[t];
807 if (need_comma && print_arg_types)
808 string_append (decl, ", ");
809 if (!do_arg (&tem, &arg, arg_mode))
810 return 0;
811 if (print_arg_types)
812 string_appends (decl, &arg);
813 string_delete (&arg);
814 need_comma = 1;
815 }
816 }
817 else
818 {
819 if (need_comma & print_arg_types)
820 string_append (decl, ", ");
821 if (!do_arg (type, &arg, arg_mode))
822 return 0;
823 if (print_arg_types)
824 string_appends (decl, &arg);
825 string_delete (&arg);
826 need_comma = 1;
827 }
828 }
829
830 if (**type == 'v')
831 *type += 1;
832 else if (**type == 'e')
833 {
834 *type += 1;
835 if (print_arg_types)
836 {
837 if (need_comma)
838 string_append (decl, ",");
839 string_append (decl, "...");
840 }
841 }
842
843 if (print_arg_types)
844 string_append (decl, ")");
845 return 1;
846}
847
848static void
849munge_function_name (name, arg_mode)
850 string *name;
851 int arg_mode;
852{
853 if (!string_empty (name) && name->p - name->b >= 3
f88e7af8 854 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
dd3b648e
RP
855 {
856 int i;
857 /* see if it's an assignment expression */
858 if (name->p - name->b >= 10 /* op$assign_ */
859 && memcmp (name->b + 3, "assign_", 7) == 0)
860 {
861 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
862 {
863 int len = name->p - name->b - 10;
864 if (strlen (optable[i].in) == len
865 && memcmp (optable[i].in, name->b + 10, len) == 0)
866 {
867 string_clear (name);
868 string_append (name, "operator");
869 string_append (name, optable[i].out);
870 string_append (name, "=");
871 return;
872 }
873 }
874 }
875 else
876 {
877 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
878 {
879 int len = name->p - name->b - 3;
880 if (strlen (optable[i].in) == len
881 && memcmp (optable[i].in, name->b + 3, len) == 0)
882 {
883 string_clear (name);
884 string_append (name, "operator");
885 string_append (name, optable[i].out);
886 return;
887 }
888 }
889 }
890 return;
891 }
892 else if (!string_empty (name) && name->p - name->b >= 5
893 && memcmp (name->b, "type$", 5) == 0)
894 {
895 /* type conversion operator */
896 string type;
897 const char *tem = name->b + 5;
898 if (do_type (&tem, &type, arg_mode))
899 {
900 string_clear (name);
901 string_append (name, "operator ");
902 string_appends (name, &type);
903 string_delete (&type);
904 return;
905 }
906 }
907}
908
909/* a mini string-handling package */
910
911static void
912string_need (s, n)
913 string *s;
914 int n;
915{
916 if (s->b == NULL)
917 {
918 if (n < 32)
919 n = 32;
920 s->p = s->b = (char *) xmalloc (n);
921 s->e = s->b + n;
922 }
923 else if (s->e - s->p < n)
924 {
925 int tem = s->p - s->b;
926 n += tem;
927 n *= 2;
928 s->b = (char *) xrealloc (s->b, n);
929 s->p = s->b + tem;
930 s->e = s->b + n;
931 }
932}
933
934static void
935string_delete (s)
936 string *s;
937{
938 if (s->b != NULL)
939 {
940 free (s->b);
941 s->b = s->e = s->p = NULL;
942 }
943}
944
945static void
946string_init (s)
947 string *s;
948{
949 s->b = s->p = s->e = NULL;
950}
951
952static void
953string_clear (s)
954 string *s;
955{
956 s->p = s->b;
957}
958
959static int
960string_empty (s)
961 string *s;
962{
963 return s->b == s->p;
964}
965
966static void
967string_append (p, s)
968 string *p;
969 const char *s;
970{
971 int n;
972 if (s == NULL || *s == '\0')
973 return;
974 n = strlen (s);
975 string_need (p, n);
976 memcpy (p->p, s, n);
977 p->p += n;
978}
979
980static void
981string_appends (p, s)
982 string *p, *s;
983{
984 int n;
985 if (s->b == s->p)
986 return;
987 n = s->p - s->b;
988 string_need (p, n);
989 memcpy (p->p, s->b, n);
990 p->p += n;
991}
992
993static void
994string_appendn (p, s, n)
995 string *p;
996 const char *s;
997 int n;
998{
999 if (n == 0)
1000 return;
1001 string_need (p, n);
1002 memcpy (p->p, s, n);
1003 p->p += n;
1004}
1005
1006static void
1007string_prepend (p, s)
1008 string *p;
1009 const char *s;
1010{
1011 if (s == NULL || *s == '\0')
1012 return;
1013 string_prependn (p, s, strlen (s));
1014}
1015
1016#if 0
1017static void
1018string_prepends (p, s)
1019 string *p, *s;
1020{
1021 if (s->b == s->p)
1022 return;
1023 string_prependn (p, s->b, s->p - s->b);
1024}
1025#endif
1026
1027static void
1028string_prependn (p, s, n)
1029 string *p;
1030 const char *s;
1031 int n;
1032{
1033 char *q;
1034
1035 if (n == 0)
1036 return;
1037 string_need (p, n);
1038 for (q = p->p - 1; q >= p->b; q--)
1039 q[n] = q[0];
1040 memcpy (p->b, s, n);
1041 p->p += n;
1042}
This page took 0.076863 seconds and 4 git commands to generate.