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, 2008
4 Free Software Foundation, Inc.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/ioctl.h>
32 #include <netinet/in.h>
35 #include <sys/socket.h>
40 #if HAVE_NETINET_TCP_H
41 #include <netinet/tcp.h>
44 #include <sys/ioctl.h>
57 #include <arpa/inet.h>
68 #ifndef HAVE_SOCKLEN_T
69 typedef int socklen_t
;
73 # define INVALID_DESCRIPTOR INVALID_SOCKET
75 # define INVALID_DESCRIPTOR -1
78 /* A cache entry for a successfully looked-up symbol. */
83 struct sym_cache
*next
;
86 /* The symbol cache. */
87 static struct sym_cache
*symbol_cache
;
89 /* If this flag has been set, assume cache misses are
91 int all_symbols_looked_up
;
94 struct ui_file
*gdb_stdlog
;
96 static int remote_desc
= INVALID_DESCRIPTOR
;
98 /* FIXME headerize? */
99 extern int using_threads
;
100 extern int debug_threads
;
103 # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
104 # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
107 /* Open a connection to a remote debugger.
108 NAME is the filename used for communication. */
111 remote_open (char *name
)
113 #if defined(F_SETFL) && defined (FASYNC)
114 int save_fcntl_flags
;
118 port_str
= strchr (name
, ':');
119 if (port_str
== NULL
)
122 error ("Only <host>:<port> is supported on this platform.");
126 if (stat (name
, &statbuf
) == 0
127 && (S_ISCHR (statbuf
.st_mode
) || S_ISFIFO (statbuf
.st_mode
)))
128 remote_desc
= open (name
, O_RDWR
);
136 perror_with_name ("Could not open remote device");
140 struct termios termios
;
141 tcgetattr (remote_desc
, &termios
);
146 termios
.c_cflag
&= ~(CSIZE
| PARENB
);
147 termios
.c_cflag
|= CLOCAL
| CS8
;
148 termios
.c_cc
[VMIN
] = 1;
149 termios
.c_cc
[VTIME
] = 0;
151 tcsetattr (remote_desc
, TCSANOW
, &termios
);
157 struct termio termio
;
158 ioctl (remote_desc
, TCGETA
, &termio
);
163 termio
.c_cflag
&= ~(CSIZE
| PARENB
);
164 termio
.c_cflag
|= CLOCAL
| CS8
;
165 termio
.c_cc
[VMIN
] = 1;
166 termio
.c_cc
[VTIME
] = 0;
168 ioctl (remote_desc
, TCSETA
, &termio
);
176 ioctl (remote_desc
, TIOCGETP
, &sg
);
178 ioctl (remote_desc
, TIOCSETP
, &sg
);
182 fprintf (stderr
, "Remote debugging using %s\n", name
);
183 #endif /* USE_WIN32API */
188 static int winsock_initialized
;
192 struct sockaddr_in sockaddr
;
196 port_str
= strchr (name
, ':');
198 port
= atoi (port_str
+ 1);
201 if (!winsock_initialized
)
205 WSAStartup (MAKEWORD (1, 0), &wsad
);
206 winsock_initialized
= 1;
210 tmp_desc
= socket (PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
212 perror_with_name ("Can't open socket");
214 /* Allow rapid reuse of this port. */
216 setsockopt (tmp_desc
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &tmp
,
219 sockaddr
.sin_family
= PF_INET
;
220 sockaddr
.sin_port
= htons (port
);
221 sockaddr
.sin_addr
.s_addr
= INADDR_ANY
;
223 if (bind (tmp_desc
, (struct sockaddr
*) &sockaddr
, sizeof (sockaddr
))
224 || listen (tmp_desc
, 1))
225 perror_with_name ("Can't bind address");
227 /* If port is zero, a random port will be selected, and the
228 fprintf below needs to know what port was selected. */
231 socklen_t len
= sizeof (sockaddr
);
232 if (getsockname (tmp_desc
, (struct sockaddr
*) &sockaddr
, &len
) < 0
233 || len
< sizeof (sockaddr
))
234 perror_with_name ("Can't determine port");
235 port
= ntohs (sockaddr
.sin_port
);
238 fprintf (stderr
, "Listening on port %d\n", port
);
241 tmp
= sizeof (sockaddr
);
242 remote_desc
= accept (tmp_desc
, (struct sockaddr
*) &sockaddr
, &tmp
);
243 if (remote_desc
== -1)
244 perror_with_name ("Accept failed");
246 /* Enable TCP keep alive process. */
248 setsockopt (remote_desc
, SOL_SOCKET
, SO_KEEPALIVE
,
249 (char *) &tmp
, sizeof (tmp
));
251 /* Tell TCP not to delay small packets. This greatly speeds up
252 interactive response. */
254 setsockopt (remote_desc
, IPPROTO_TCP
, TCP_NODELAY
,
255 (char *) &tmp
, sizeof (tmp
));
259 close (tmp_desc
); /* No longer need this */
261 signal (SIGPIPE
, SIG_IGN
); /* If we don't do this, then gdbserver simply
262 exits when the remote side dies. */
264 closesocket (tmp_desc
); /* No longer need this */
267 /* Convert IP address to string. */
268 fprintf (stderr
, "Remote debugging from host %s\n",
269 inet_ntoa (sockaddr
.sin_addr
));
272 #if defined(F_SETFL) && defined (FASYNC)
273 save_fcntl_flags
= fcntl (remote_desc
, F_GETFL
, 0);
274 fcntl (remote_desc
, F_SETFL
, save_fcntl_flags
| FASYNC
);
275 #if defined (F_SETOWN)
276 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 unblock_async_io (void)
654 sigemptyset (&sigio_set
);
655 sigaddset (&sigio_set
, SIGIO
);
656 sigprocmask (SIG_UNBLOCK
, &sigio_set
, NULL
);
660 /* Current state of asynchronous I/O. */
661 static int async_io_enabled
;
663 /* Enable asynchronous I/O. */
665 enable_async_io (void)
667 if (async_io_enabled
)
671 signal (SIGIO
, input_interrupt
);
673 async_io_enabled
= 1;
676 /* Disable asynchronous I/O. */
678 disable_async_io (void)
680 if (!async_io_enabled
)
684 signal (SIGIO
, SIG_IGN
);
686 async_io_enabled
= 0;
690 initialize_async_io (void)
692 /* Make sure that async I/O starts disabled. */
693 async_io_enabled
= 1;
696 /* Make sure the signal is unblocked. */
700 /* Returns next char from remote GDB. -1 if error. */
705 static unsigned char buf
[BUFSIZ
];
706 static int bufcnt
= 0;
707 static unsigned char *bufp
;
712 bufcnt
= read (remote_desc
, buf
, sizeof (buf
));
717 fprintf (stderr
, "readchar: Got EOF\n");
729 /* Read a packet from the remote machine, with error checking,
730 and store it in BUF. Returns length of packet, or negative if error. */
736 unsigned char csum
, c1
, c2
;
750 fprintf (stderr
, "[getpkt: discarding char '%c']\n", c
);
771 c1
= fromhex (readchar ());
772 c2
= fromhex (readchar ());
774 if (csum
== (c1
<< 4) + c2
)
777 fprintf (stderr
, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
778 (c1
<< 4) + c2
, csum
, buf
);
779 write (remote_desc
, "-", 1);
784 fprintf (stderr
, "getpkt (\"%s\"); [sending ack] \n", buf
);
788 write (remote_desc
, "+", 1);
792 fprintf (stderr
, "[sent ack]\n");
808 write_enn (char *buf
)
810 /* Some day, we should define the meanings of the error codes... */
818 convert_int_to_ascii (unsigned char *from
, char *to
, int n
)
825 nib
= ((ch
& 0xf0) >> 4) & 0x0f;
835 convert_ascii_to_int (char *from
, unsigned char *to
, int n
)
840 nib1
= fromhex (*from
++);
841 nib2
= fromhex (*from
++);
842 *to
++ = (((nib1
& 0x0f) << 4) & 0xf0) | (nib2
& 0x0f);
847 outreg (int regno
, char *buf
)
849 if ((regno
>> 12) != 0)
850 *buf
++ = tohex ((regno
>> 12) & 0xf);
851 if ((regno
>> 8) != 0)
852 *buf
++ = tohex ((regno
>> 8) & 0xf);
853 *buf
++ = tohex ((regno
>> 4) & 0xf);
854 *buf
++ = tohex (regno
& 0xf);
856 collect_register_as_string (regno
, buf
);
857 buf
+= 2 * register_size (regno
);
864 new_thread_notify (int id
)
868 /* The `n' response is not yet part of the remote protocol. Do nothing. */
872 if (server_waiting
== 0)
875 sprintf (own_buf
, "n%x", id
);
882 dead_thread_notify (int id
)
886 /* The `x' response is not yet part of the remote protocol. Do nothing. */
890 sprintf (own_buf
, "x%x", id
);
897 prepare_resume_reply (char *buf
, char status
, unsigned char sig
)
903 nib
= ((sig
& 0xf0) >> 4);
904 *buf
++ = tohex (nib
);
906 *buf
++ = tohex (nib
);
910 const char **regp
= gdbserver_expedite_regs
;
912 if (the_target
->stopped_by_watchpoint
!= NULL
913 && (*the_target
->stopped_by_watchpoint
) ())
918 strncpy (buf
, "watch:", 6);
921 addr
= (*the_target
->stopped_data_address
) ();
923 /* Convert each byte of the address into two hexadecimal chars.
924 Note that we take sizeof (void *) instead of sizeof (addr);
925 this is to avoid sending a 64-bit address to a 32-bit GDB. */
926 for (i
= sizeof (void *) * 2; i
> 0; i
--)
928 *buf
++ = tohex ((addr
>> (i
- 1) * 4) & 0xf);
935 buf
= outreg (find_regno (*regp
), buf
);
939 /* Formerly, if the debugger had not used any thread features we would not
940 burden it with a thread status response. This was for the benefit of
941 GDB 4.13 and older. However, in recent GDB versions the check
942 (``if (cont_thread != 0)'') does not have the desired effect because of
943 sillyness in the way that the remote protocol handles specifying a thread.
944 Since thread support relies on qSymbol support anyway, assume GDB can handle
949 unsigned int gdb_id_from_wait
;
951 /* FIXME right place to set this? */
952 thread_from_wait
= ((struct inferior_list_entry
*)current_inferior
)->id
;
953 gdb_id_from_wait
= thread_to_gdb_id (current_inferior
);
956 fprintf (stderr
, "Writing resume reply for %ld\n\n", thread_from_wait
);
957 /* This if (1) ought to be unnecessary. But remote_wait in GDB
958 will claim this event belongs to inferior_ptid if we do not
959 specify a thread, and there's no way for gdbserver to know
960 what inferior_ptid is. */
961 if (1 || old_thread_from_wait
!= thread_from_wait
)
963 general_thread
= thread_from_wait
;
964 sprintf (buf
, "thread:%x;", gdb_id_from_wait
);
966 old_thread_from_wait
= thread_from_wait
;
972 strcpy (buf
, "library:;");
977 /* For W and X, we're done. */
982 decode_m_packet (char *from
, CORE_ADDR
*mem_addr_ptr
, unsigned int *len_ptr
)
986 *mem_addr_ptr
= *len_ptr
= 0;
988 while ((ch
= from
[i
++]) != ',')
990 *mem_addr_ptr
= *mem_addr_ptr
<< 4;
991 *mem_addr_ptr
|= fromhex (ch
) & 0x0f;
994 for (j
= 0; j
< 4; j
++)
996 if ((ch
= from
[i
++]) == 0)
998 *len_ptr
= *len_ptr
<< 4;
999 *len_ptr
|= fromhex (ch
) & 0x0f;
1004 decode_M_packet (char *from
, CORE_ADDR
*mem_addr_ptr
, unsigned int *len_ptr
,
1009 *mem_addr_ptr
= *len_ptr
= 0;
1011 while ((ch
= from
[i
++]) != ',')
1013 *mem_addr_ptr
= *mem_addr_ptr
<< 4;
1014 *mem_addr_ptr
|= fromhex (ch
) & 0x0f;
1017 while ((ch
= from
[i
++]) != ':')
1019 *len_ptr
= *len_ptr
<< 4;
1020 *len_ptr
|= fromhex (ch
) & 0x0f;
1023 convert_ascii_to_int (&from
[i
++], to
, *len_ptr
);
1027 decode_X_packet (char *from
, int packet_len
, CORE_ADDR
*mem_addr_ptr
,
1028 unsigned int *len_ptr
, unsigned char *to
)
1032 *mem_addr_ptr
= *len_ptr
= 0;
1034 while ((ch
= from
[i
++]) != ',')
1036 *mem_addr_ptr
= *mem_addr_ptr
<< 4;
1037 *mem_addr_ptr
|= fromhex (ch
) & 0x0f;
1040 while ((ch
= from
[i
++]) != ':')
1042 *len_ptr
= *len_ptr
<< 4;
1043 *len_ptr
|= fromhex (ch
) & 0x0f;
1046 if (remote_unescape_input ((const gdb_byte
*) &from
[i
], packet_len
- i
,
1047 to
, *len_ptr
) != *len_ptr
)
1053 /* Decode a qXfer write request. */
1055 decode_xfer_write (char *buf
, int packet_len
, char **annex
, CORE_ADDR
*offset
,
1056 unsigned int *len
, unsigned char *data
)
1060 /* Extract and NUL-terminate the annex. */
1062 while (*buf
&& *buf
!= ':')
1068 /* Extract the offset. */
1070 while ((ch
= *buf
++) != ':')
1072 *offset
= *offset
<< 4;
1073 *offset
|= fromhex (ch
) & 0x0f;
1076 /* Get encoded data. */
1077 packet_len
-= buf
- *annex
;
1078 *len
= remote_unescape_input ((const gdb_byte
*) buf
, packet_len
,
1083 /* Ask GDB for the address of NAME, and return it in ADDRP if found.
1084 Returns 1 if the symbol is found, 0 if it is not, -1 on error. */
1087 look_up_one_symbol (const char *name
, CORE_ADDR
*addrp
)
1089 char own_buf
[266], *p
, *q
;
1091 struct sym_cache
*sym
;
1093 /* Check the cache first. */
1094 for (sym
= symbol_cache
; sym
; sym
= sym
->next
)
1095 if (strcmp (name
, sym
->name
) == 0)
1101 /* If we've passed the call to thread_db_look_up_symbols, then
1102 anything not in the cache must not exist; we're not interested
1103 in any libraries loaded after that point, only in symbols in
1104 libpthread.so. It might not be an appropriate time to look
1105 up a symbol, e.g. while we're trying to fetch registers. */
1106 if (all_symbols_looked_up
)
1109 /* Send the request. */
1110 strcpy (own_buf
, "qSymbol:");
1111 hexify (own_buf
+ strlen ("qSymbol:"), name
, strlen (name
));
1112 if (putpkt (own_buf
) < 0)
1115 /* FIXME: Eventually add buffer overflow checking (to getpkt?) */
1116 len
= getpkt (own_buf
);
1120 /* We ought to handle pretty much any packet at this point while we
1121 wait for the qSymbol "response". That requires re-entering the
1122 main loop. For now, this is an adequate approximation; allow
1123 GDB to read from memory while it figures out the address of the
1125 while (own_buf
[0] == 'm')
1128 unsigned char *mem_buf
;
1129 unsigned int mem_len
;
1131 decode_m_packet (&own_buf
[1], &mem_addr
, &mem_len
);
1132 mem_buf
= malloc (mem_len
);
1133 if (read_inferior_memory (mem_addr
, mem_buf
, mem_len
) == 0)
1134 convert_int_to_ascii (mem_buf
, own_buf
, mem_len
);
1136 write_enn (own_buf
);
1138 if (putpkt (own_buf
) < 0)
1140 len
= getpkt (own_buf
);
1145 if (strncmp (own_buf
, "qSymbol:", strlen ("qSymbol:")) != 0)
1147 warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf
);
1151 p
= own_buf
+ strlen ("qSymbol:");
1153 while (*q
&& *q
!= ':')
1156 /* Make sure we found a value for the symbol. */
1157 if (p
== q
|| *q
== '\0')
1160 decode_address (addrp
, p
, q
- p
);
1162 /* Save the symbol in our cache. */
1163 sym
= malloc (sizeof (*sym
));
1164 sym
->name
= strdup (name
);
1166 sym
->next
= symbol_cache
;
1173 monitor_output (const char *msg
)
1175 char *buf
= malloc (strlen (msg
) * 2 + 2);
1178 hexify (buf
+ 1, msg
, 0);
1184 /* Return a malloc allocated string with special characters from TEXT
1185 replaced by entity references. */
1188 xml_escape_text (const char *text
)
1193 /* Compute the length of the result. */
1194 for (i
= 0, special
= 0; text
[i
] != '\0'; i
++)
1212 /* Expand the result. */
1213 result
= malloc (i
+ special
+ 1);
1214 for (i
= 0, special
= 0; text
[i
] != '\0'; i
++)
1218 strcpy (result
+ i
+ special
, "'");
1222 strcpy (result
+ i
+ special
, """);
1226 strcpy (result
+ i
+ special
, "&");
1230 strcpy (result
+ i
+ special
, "<");
1234 strcpy (result
+ i
+ special
, ">");
1238 result
[i
+ special
] = text
[i
];
1241 result
[i
+ special
] = '\0';
This page took 0.05425 seconds and 4 git commands to generate.