1 /* Remote utility routines for the remote server for GDB.
2 Copyright (C) 1986, 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
25 #include <sys/ioctl.h>
31 #include <netinet/in.h>
34 #include <sys/socket.h>
39 #if HAVE_NETINET_TCP_H
40 #include <netinet/tcp.h>
43 #include <sys/ioctl.h>
56 #include <arpa/inet.h>
67 #ifndef HAVE_SOCKLEN_T
68 typedef int socklen_t
;
72 # define INVALID_DESCRIPTOR INVALID_SOCKET
74 # define INVALID_DESCRIPTOR -1
77 /* A cache entry for a successfully looked-up symbol. */
82 struct sym_cache
*next
;
85 /* The symbol cache. */
86 static struct sym_cache
*symbol_cache
;
88 /* If this flag has been set, assume cache misses are
90 int all_symbols_looked_up
;
93 struct ui_file
*gdb_stdlog
;
95 static int remote_desc
= INVALID_DESCRIPTOR
;
97 /* FIXME headerize? */
98 extern int using_threads
;
99 extern int debug_threads
;
102 # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
103 # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
106 /* Open a connection to a remote debugger.
107 NAME is the filename used for communication. */
110 remote_open (char *name
)
112 #if defined(F_SETFL) && defined (FASYNC)
113 int save_fcntl_flags
;
117 port_str
= strchr (name
, ':');
118 if (port_str
== NULL
)
121 error ("Only <host>:<port> is supported on this platform.");
125 if (stat (name
, &statbuf
) == 0
126 && (S_ISCHR (statbuf
.st_mode
) || S_ISFIFO (statbuf
.st_mode
)))
127 remote_desc
= open (name
, O_RDWR
);
135 perror_with_name ("Could not open remote device");
139 struct termios termios
;
140 tcgetattr (remote_desc
, &termios
);
145 termios
.c_cflag
&= ~(CSIZE
| PARENB
);
146 termios
.c_cflag
|= CLOCAL
| CS8
;
147 termios
.c_cc
[VMIN
] = 1;
148 termios
.c_cc
[VTIME
] = 0;
150 tcsetattr (remote_desc
, TCSANOW
, &termios
);
156 struct termio termio
;
157 ioctl (remote_desc
, TCGETA
, &termio
);
162 termio
.c_cflag
&= ~(CSIZE
| PARENB
);
163 termio
.c_cflag
|= CLOCAL
| CS8
;
164 termio
.c_cc
[VMIN
] = 1;
165 termio
.c_cc
[VTIME
] = 0;
167 ioctl (remote_desc
, TCSETA
, &termio
);
175 ioctl (remote_desc
, TIOCGETP
, &sg
);
177 ioctl (remote_desc
, TIOCSETP
, &sg
);
181 fprintf (stderr
, "Remote debugging using %s\n", name
);
182 #endif /* USE_WIN32API */
187 static int winsock_initialized
;
191 struct sockaddr_in sockaddr
;
195 port_str
= strchr (name
, ':');
197 port
= atoi (port_str
+ 1);
200 if (!winsock_initialized
)
204 WSAStartup (MAKEWORD (1, 0), &wsad
);
205 winsock_initialized
= 1;
209 tmp_desc
= socket (PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
211 perror_with_name ("Can't open socket");
213 /* Allow rapid reuse of this port. */
215 setsockopt (tmp_desc
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &tmp
,
218 sockaddr
.sin_family
= PF_INET
;
219 sockaddr
.sin_port
= htons (port
);
220 sockaddr
.sin_addr
.s_addr
= INADDR_ANY
;
222 if (bind (tmp_desc
, (struct sockaddr
*) &sockaddr
, sizeof (sockaddr
))
223 || listen (tmp_desc
, 1))
224 perror_with_name ("Can't bind address");
226 /* If port is zero, a random port will be selected, and the
227 fprintf below needs to know what port was selected. */
230 socklen_t len
= sizeof (sockaddr
);
231 if (getsockname (tmp_desc
, (struct sockaddr
*) &sockaddr
, &len
) < 0
232 || len
< sizeof (sockaddr
))
233 perror_with_name ("Can't determine port");
234 port
= ntohs (sockaddr
.sin_port
);
237 fprintf (stderr
, "Listening on port %d\n", port
);
240 tmp
= sizeof (sockaddr
);
241 remote_desc
= accept (tmp_desc
, (struct sockaddr
*) &sockaddr
, &tmp
);
242 if (remote_desc
== -1)
243 perror_with_name ("Accept failed");
245 /* Enable TCP keep alive process. */
247 setsockopt (remote_desc
, SOL_SOCKET
, SO_KEEPALIVE
,
248 (char *) &tmp
, sizeof (tmp
));
250 /* Tell TCP not to delay small packets. This greatly speeds up
251 interactive response. */
253 setsockopt (remote_desc
, IPPROTO_TCP
, TCP_NODELAY
,
254 (char *) &tmp
, sizeof (tmp
));
258 close (tmp_desc
); /* No longer need this */
260 signal (SIGPIPE
, SIG_IGN
); /* If we don't do this, then gdbserver simply
261 exits when the remote side dies. */
263 closesocket (tmp_desc
); /* No longer need this */
266 /* Convert IP address to string. */
267 fprintf (stderr
, "Remote debugging from host %s\n",
268 inet_ntoa (sockaddr
.sin_addr
));
271 #if defined(F_SETFL) && defined (FASYNC)
272 save_fcntl_flags
= fcntl (remote_desc
, F_GETFL
, 0);
273 fcntl (remote_desc
, F_SETFL
, save_fcntl_flags
| FASYNC
);
274 #if defined (F_SETOWN)
275 fcntl (remote_desc
, F_SETOWN
, getpid ());
285 closesocket (remote_desc
);
291 /* Convert hex digit A to a number. */
296 if (a
>= '0' && a
<= '9')
298 else if (a
>= 'a' && a
<= 'f')
301 error ("Reply contains invalid hex digit");
306 unhexify (char *bin
, const char *hex
, int count
)
310 for (i
= 0; i
< count
; i
++)
312 if (hex
[0] == 0 || hex
[1] == 0)
314 /* Hex string is short, or of uneven length.
315 Return the count that has been converted so far. */
318 *bin
++ = fromhex (hex
[0]) * 16 + fromhex (hex
[1]);
325 decode_address (CORE_ADDR
*addrp
, const char *start
, int len
)
332 for (i
= 0; i
< len
; i
++)
336 addr
= addr
| (fromhex (ch
) & 0x0f);
342 decode_address_to_semicolon (CORE_ADDR
*addrp
, const char *start
)
347 while (*end
!= '\0' && *end
!= ';')
350 decode_address (addrp
, start
, end
- start
);
357 /* Convert number NIB to a hex digit. */
365 return 'a' + nib
- 10;
369 hexify (char *hex
, const char *bin
, int count
)
373 /* May use a length, or a nul-terminated string as input. */
375 count
= strlen (bin
);
377 for (i
= 0; i
< count
; i
++)
379 *hex
++ = tohex ((*bin
>> 4) & 0xf);
380 *hex
++ = tohex (*bin
++ & 0xf);
386 /* Convert BUFFER, binary data at least LEN bytes long, into escaped
387 binary data in OUT_BUF. Set *OUT_LEN to the length of the data
388 encoded in OUT_BUF, and return the number of bytes in OUT_BUF
389 (which may be more than *OUT_LEN due to escape characters). The
390 total number of bytes in the output buffer will be at most
394 remote_escape_output (const gdb_byte
*buffer
, int len
,
395 gdb_byte
*out_buf
, int *out_len
,
398 int input_index
, output_index
;
401 for (input_index
= 0; input_index
< len
; input_index
++)
403 gdb_byte b
= buffer
[input_index
];
405 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
407 /* These must be escaped. */
408 if (output_index
+ 2 > out_maxlen
)
410 out_buf
[output_index
++] = '}';
411 out_buf
[output_index
++] = b
^ 0x20;
415 if (output_index
+ 1 > out_maxlen
)
417 out_buf
[output_index
++] = b
;
421 *out_len
= input_index
;
425 /* Convert BUFFER, escaped data LEN bytes long, into binary data
426 in OUT_BUF. Return the number of bytes written to OUT_BUF.
427 Raise an error if the total number of bytes exceeds OUT_MAXLEN.
429 This function reverses remote_escape_output. It allows more
430 escaped characters than that function does, in particular because
431 '*' must be escaped to avoid the run-length encoding processing
432 in reading packets. */
435 remote_unescape_input (const gdb_byte
*buffer
, int len
,
436 gdb_byte
*out_buf
, int out_maxlen
)
438 int input_index
, output_index
;
443 for (input_index
= 0; input_index
< len
; input_index
++)
445 gdb_byte b
= buffer
[input_index
];
447 if (output_index
+ 1 > out_maxlen
)
448 error ("Received too much data from the target.");
452 out_buf
[output_index
++] = b
^ 0x20;
458 out_buf
[output_index
++] = b
;
462 error ("Unmatched escape character in target response.");
467 /* Look for a sequence of characters which can be run-length encoded.
468 If there are any, update *CSUM and *P. Otherwise, output the
469 single character. Return the number of characters consumed. */
472 try_rle (char *buf
, int remaining
, unsigned char *csum
, char **p
)
476 /* Always output the character. */
480 /* Don't go past '~'. */
484 for (n
= 1; n
< remaining
; n
++)
485 if (buf
[n
] != buf
[0])
488 /* N is the index of the first character not the same as buf[0].
489 buf[0] is counted twice, so by decrementing N, we get the number
490 of characters the RLE sequence will replace. */
496 /* Skip the frame characters. The manual says to skip '+' and '-'
497 also, but there's no reason to. Unfortunately these two unusable
498 characters double the encoded length of a four byte zero
500 while (n
+ 29 == '$' || n
+ 29 == '#')
511 /* Send a packet to the remote machine, with error checking.
512 The data of the packet is in BUF, and the length of the
513 packet is in CNT. Returns >= 0 on success, -1 otherwise. */
516 putpkt_binary (char *buf
, int cnt
)
519 unsigned char csum
= 0;
524 buf2
= malloc (PBUFSIZ
);
526 /* Copy the packet into buffer BUF2, encapsulating it
527 and giving it a checksum. */
532 for (i
= 0; i
< cnt
;)
533 i
+= try_rle (buf
+ i
, cnt
- i
, &csum
, &p
);
536 *p
++ = tohex ((csum
>> 4) & 0xf);
537 *p
++ = tohex (csum
& 0xf);
541 /* Send it over and over until we get a positive ack. */
547 if (write (remote_desc
, buf2
, p
- buf2
) != p
- buf2
)
549 perror ("putpkt(write)");
556 fprintf (stderr
, "putpkt (\"%s\"); [looking for ack]\n", buf2
);
559 cc
= read (remote_desc
, buf3
, 1);
562 fprintf (stderr
, "[received '%c' (0x%x)]\n", buf3
[0], buf3
[0]);
569 fprintf (stderr
, "putpkt(read): Got EOF\n");
571 perror ("putpkt(read)");
577 /* Check for an input interrupt while we're here. */
578 if (buf3
[0] == '\003')
579 (*the_target
->request_interrupt
) ();
581 while (buf3
[0] != '+');
584 return 1; /* Success! */
587 /* Send a packet to the remote machine, with error checking. The data
588 of the packet is in BUF, and the packet should be a NUL-terminated
589 string. Returns >= 0 on success, -1 otherwise. */
594 return putpkt_binary (buf
, strlen (buf
));
597 /* Come here when we get an input interrupt from the remote side. This
598 interrupt should only be active while we are waiting for the child to do
599 something. About the only thing that should come through is a ^C, which
600 will cause us to request child interruption. */
603 input_interrupt (int unused
)
606 struct timeval immediate
= { 0, 0 };
608 /* Protect against spurious interrupts. This has been observed to
609 be a problem under NetBSD 1.4 and 1.5. */
612 FD_SET (remote_desc
, &readset
);
613 if (select (remote_desc
+ 1, &readset
, 0, 0, &immediate
) > 0)
618 cc
= read (remote_desc
, &c
, 1);
620 if (cc
!= 1 || c
!= '\003')
622 fprintf (stderr
, "input_interrupt, count = %d c = %d ('%c')\n",
627 (*the_target
->request_interrupt
) ();
631 /* Check if the remote side sent us an interrupt request (^C). */
633 check_remote_input_interrupt_request (void)
635 /* This function may be called before establishing communications,
636 therefore we need to validate the remote descriptor. */
638 if (remote_desc
== INVALID_DESCRIPTOR
)
644 /* Asynchronous I/O support. SIGIO must be enabled when waiting, in order to
645 accept Control-C from the client, and must be disabled when talking to
649 block_async_io (void)
653 sigemptyset (&sigio_set
);
654 sigaddset (&sigio_set
, SIGIO
);
655 sigprocmask (SIG_BLOCK
, &sigio_set
, NULL
);
660 unblock_async_io (void)
664 sigemptyset (&sigio_set
);
665 sigaddset (&sigio_set
, SIGIO
);
666 sigprocmask (SIG_UNBLOCK
, &sigio_set
, NULL
);
670 /* Current state of asynchronous I/O. */
671 static int async_io_enabled
;
673 /* Enable asynchronous I/O. */
675 enable_async_io (void)
677 if (async_io_enabled
)
681 signal (SIGIO
, input_interrupt
);
683 async_io_enabled
= 1;
686 /* Disable asynchronous I/O. */
688 disable_async_io (void)
690 if (!async_io_enabled
)
694 signal (SIGIO
, SIG_IGN
);
696 async_io_enabled
= 0;
699 /* Returns next char from remote GDB. -1 if error. */
704 static unsigned char buf
[BUFSIZ
];
705 static int bufcnt
= 0;
706 static unsigned char *bufp
;
711 bufcnt
= read (remote_desc
, buf
, sizeof (buf
));
716 fprintf (stderr
, "readchar: Got EOF\n");
725 return *bufp
++ & 0x7f;
728 /* Read a packet from the remote machine, with error checking,
729 and store it in BUF. Returns length of packet, or negative if error. */
735 unsigned char csum
, c1
, c2
;
749 fprintf (stderr
, "[getpkt: discarding char '%c']\n", c
);
770 c1
= fromhex (readchar ());
771 c2
= fromhex (readchar ());
773 if (csum
== (c1
<< 4) + c2
)
776 fprintf (stderr
, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
777 (c1
<< 4) + c2
, csum
, buf
);
778 write (remote_desc
, "-", 1);
783 fprintf (stderr
, "getpkt (\"%s\"); [sending ack] \n", buf
);
787 write (remote_desc
, "+", 1);
791 fprintf (stderr
, "[sent ack]\n");
807 write_enn (char *buf
)
809 /* Some day, we should define the meanings of the error codes... */
817 convert_int_to_ascii (unsigned char *from
, char *to
, int n
)
824 nib
= ((ch
& 0xf0) >> 4) & 0x0f;
834 convert_ascii_to_int (char *from
, unsigned char *to
, int n
)
839 nib1
= fromhex (*from
++);
840 nib2
= fromhex (*from
++);
841 *to
++ = (((nib1
& 0x0f) << 4) & 0xf0) | (nib2
& 0x0f);
846 outreg (int regno
, char *buf
)
848 if ((regno
>> 12) != 0)
849 *buf
++ = tohex ((regno
>> 12) & 0xf);
850 if ((regno
>> 8) != 0)
851 *buf
++ = tohex ((regno
>> 8) & 0xf);
852 *buf
++ = tohex ((regno
>> 4) & 0xf);
853 *buf
++ = tohex (regno
& 0xf);
855 collect_register_as_string (regno
, buf
);
856 buf
+= 2 * register_size (regno
);
863 new_thread_notify (int id
)
867 /* The `n' response is not yet part of the remote protocol. Do nothing. */
871 if (server_waiting
== 0)
874 sprintf (own_buf
, "n%x", id
);
881 dead_thread_notify (int id
)
885 /* The `x' response is not yet part of the remote protocol. Do nothing. */
889 sprintf (own_buf
, "x%x", id
);
896 prepare_resume_reply (char *buf
, char status
, unsigned char sig
)
902 nib
= ((sig
& 0xf0) >> 4);
903 *buf
++ = tohex (nib
);
905 *buf
++ = tohex (nib
);
909 const char **regp
= gdbserver_expedite_regs
;
911 if (the_target
->stopped_by_watchpoint
!= NULL
912 && (*the_target
->stopped_by_watchpoint
) ())
917 strncpy (buf
, "watch:", 6);
920 addr
= (*the_target
->stopped_data_address
) ();
922 /* Convert each byte of the address into two hexadecimal chars.
923 Note that we take sizeof (void *) instead of sizeof (addr);
924 this is to avoid sending a 64-bit address to a 32-bit GDB. */
925 for (i
= sizeof (void *) * 2; i
> 0; i
--)
927 *buf
++ = tohex ((addr
>> (i
- 1) * 4) & 0xf);
934 buf
= outreg (find_regno (*regp
), buf
);
938 /* Formerly, if the debugger had not used any thread features we would not
939 burden it with a thread status response. This was for the benefit of
940 GDB 4.13 and older. However, in recent GDB versions the check
941 (``if (cont_thread != 0)'') does not have the desired effect because of
942 sillyness in the way that the remote protocol handles specifying a thread.
943 Since thread support relies on qSymbol support anyway, assume GDB can handle
948 unsigned int gdb_id_from_wait
;
950 /* FIXME right place to set this? */
951 thread_from_wait
= ((struct inferior_list_entry
*)current_inferior
)->id
;
952 gdb_id_from_wait
= thread_to_gdb_id (current_inferior
);
955 fprintf (stderr
, "Writing resume reply for %ld\n\n", thread_from_wait
);
956 /* This if (1) ought to be unnecessary. But remote_wait in GDB
957 will claim this event belongs to inferior_ptid if we do not
958 specify a thread, and there's no way for gdbserver to know
959 what inferior_ptid is. */
960 if (1 || old_thread_from_wait
!= thread_from_wait
)
962 general_thread
= thread_from_wait
;
963 sprintf (buf
, "thread:%x;", gdb_id_from_wait
);
965 old_thread_from_wait
= thread_from_wait
;
971 strcpy (buf
, "library:;");
976 /* For W and X, we're done. */
981 decode_m_packet (char *from
, CORE_ADDR
*mem_addr_ptr
, unsigned int *len_ptr
)
985 *mem_addr_ptr
= *len_ptr
= 0;
987 while ((ch
= from
[i
++]) != ',')
989 *mem_addr_ptr
= *mem_addr_ptr
<< 4;
990 *mem_addr_ptr
|= fromhex (ch
) & 0x0f;
993 for (j
= 0; j
< 4; j
++)
995 if ((ch
= from
[i
++]) == 0)
997 *len_ptr
= *len_ptr
<< 4;
998 *len_ptr
|= fromhex (ch
) & 0x0f;
1003 decode_M_packet (char *from
, CORE_ADDR
*mem_addr_ptr
, unsigned int *len_ptr
,
1008 *mem_addr_ptr
= *len_ptr
= 0;
1010 while ((ch
= from
[i
++]) != ',')
1012 *mem_addr_ptr
= *mem_addr_ptr
<< 4;
1013 *mem_addr_ptr
|= fromhex (ch
) & 0x0f;
1016 while ((ch
= from
[i
++]) != ':')
1018 *len_ptr
= *len_ptr
<< 4;
1019 *len_ptr
|= fromhex (ch
) & 0x0f;
1022 convert_ascii_to_int (&from
[i
++], to
, *len_ptr
);
1026 decode_X_packet (char *from
, int packet_len
, CORE_ADDR
*mem_addr_ptr
,
1027 unsigned int *len_ptr
, unsigned char *to
)
1031 *mem_addr_ptr
= *len_ptr
= 0;
1033 while ((ch
= from
[i
++]) != ',')
1035 *mem_addr_ptr
= *mem_addr_ptr
<< 4;
1036 *mem_addr_ptr
|= fromhex (ch
) & 0x0f;
1039 while ((ch
= from
[i
++]) != ':')
1041 *len_ptr
= *len_ptr
<< 4;
1042 *len_ptr
|= fromhex (ch
) & 0x0f;
1045 if (remote_unescape_input ((const gdb_byte
*) &from
[i
], packet_len
- i
,
1046 to
, *len_ptr
) != *len_ptr
)
1052 /* Decode a qXfer write request. */
1054 decode_xfer_write (char *buf
, int packet_len
, char **annex
, CORE_ADDR
*offset
,
1055 unsigned int *len
, unsigned char *data
)
1059 /* Extract and NUL-terminate the annex. */
1061 while (*buf
&& *buf
!= ':')
1067 /* Extract the offset. */
1069 while ((ch
= *buf
++) != ':')
1071 *offset
= *offset
<< 4;
1072 *offset
|= fromhex (ch
) & 0x0f;
1075 /* Get encoded data. */
1076 packet_len
-= buf
- *annex
;
1077 *len
= remote_unescape_input ((const gdb_byte
*) buf
, packet_len
,
1082 /* Ask GDB for the address of NAME, and return it in ADDRP if found.
1083 Returns 1 if the symbol is found, 0 if it is not, -1 on error. */
1086 look_up_one_symbol (const char *name
, CORE_ADDR
*addrp
)
1088 char own_buf
[266], *p
, *q
;
1090 struct sym_cache
*sym
;
1092 /* Check the cache first. */
1093 for (sym
= symbol_cache
; sym
; sym
= sym
->next
)
1094 if (strcmp (name
, sym
->name
) == 0)
1100 /* If we've passed the call to thread_db_look_up_symbols, then
1101 anything not in the cache must not exist; we're not interested
1102 in any libraries loaded after that point, only in symbols in
1103 libpthread.so. It might not be an appropriate time to look
1104 up a symbol, e.g. while we're trying to fetch registers. */
1105 if (all_symbols_looked_up
)
1108 /* Send the request. */
1109 strcpy (own_buf
, "qSymbol:");
1110 hexify (own_buf
+ strlen ("qSymbol:"), name
, strlen (name
));
1111 if (putpkt (own_buf
) < 0)
1114 /* FIXME: Eventually add buffer overflow checking (to getpkt?) */
1115 len
= getpkt (own_buf
);
1119 /* We ought to handle pretty much any packet at this point while we
1120 wait for the qSymbol "response". That requires re-entering the
1121 main loop. For now, this is an adequate approximation; allow
1122 GDB to read from memory while it figures out the address of the
1124 while (own_buf
[0] == 'm')
1127 unsigned char *mem_buf
;
1128 unsigned int mem_len
;
1130 decode_m_packet (&own_buf
[1], &mem_addr
, &mem_len
);
1131 mem_buf
= malloc (mem_len
);
1132 if (read_inferior_memory (mem_addr
, mem_buf
, mem_len
) == 0)
1133 convert_int_to_ascii (mem_buf
, own_buf
, mem_len
);
1135 write_enn (own_buf
);
1137 if (putpkt (own_buf
) < 0)
1139 len
= getpkt (own_buf
);
1144 if (strncmp (own_buf
, "qSymbol:", strlen ("qSymbol:")) != 0)
1146 warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf
);
1150 p
= own_buf
+ strlen ("qSymbol:");
1152 while (*q
&& *q
!= ':')
1155 /* Make sure we found a value for the symbol. */
1156 if (p
== q
|| *q
== '\0')
1159 decode_address (addrp
, p
, q
- p
);
1161 /* Save the symbol in our cache. */
1162 sym
= malloc (sizeof (*sym
));
1163 sym
->name
= strdup (name
);
1165 sym
->next
= symbol_cache
;
1172 monitor_output (const char *msg
)
1174 char *buf
= malloc (strlen (msg
) * 2 + 2);
1177 hexify (buf
+ 1, msg
, 0);
1183 /* Return a malloc allocated string with special characters from TEXT
1184 replaced by entity references. */
1187 xml_escape_text (const char *text
)
1192 /* Compute the length of the result. */
1193 for (i
= 0, special
= 0; text
[i
] != '\0'; i
++)
1211 /* Expand the result. */
1212 result
= malloc (i
+ special
+ 1);
1213 for (i
= 0, special
= 0; text
[i
] != '\0'; i
++)
1217 strcpy (result
+ i
+ special
, "'");
1221 strcpy (result
+ i
+ special
, """);
1225 strcpy (result
+ i
+ special
, "&");
1229 strcpy (result
+ i
+ special
, "<");
1233 strcpy (result
+ i
+ special
, ">");
1237 result
[i
+ special
] = text
[i
];
1240 result
[i
+ special
] = '\0';
This page took 0.055091 seconds and 4 git commands to generate.