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