static void continuation_test(int continuations) { int i; for(i = 0; i < continuations; ++i) { continuation_block_t continuation = {.block = continuation_0}; int c = open_continuation(NULL, 0, continuation_release, 0); assert(c >= 0); printf("Continuation [%d] opened\n", c); mark_continuation(c); continuation.arg = (void*)make_scope(c); assert(add_continuation(c, &continuation, 1) == 0); } continuation_player(); }
/* NOTE: 1999-04-30 This is the asynchronous version of the command_loop function. The command_loop function will be obsolete when we switch to use the event loop at every execution of gdb. */ static void command_handler (char *command) { struct cleanup *old_chain; int stdin_is_tty = ISATTY (stdin); struct continuation_arg *arg1; struct continuation_arg *arg2; long time_at_cmd_start; #ifdef HAVE_SBRK long space_at_cmd_start = 0; #endif extern int display_time; extern int display_space; quit_flag = 0; if (instream == stdin && stdin_is_tty) reinitialize_more_filter (); old_chain = make_cleanup (null_cleanup, 0); /* If readline returned a NULL command, it means that the connection with the terminal is gone. This happens at the end of a testsuite run, after Expect has hung up but GDB is still alive. In such a case, we just quit gdb killing the inferior program too. */ if (command == 0) quit_command ((char *) 0, stdin == instream); time_at_cmd_start = get_run_time (); if (display_space) { #ifdef HAVE_SBRK char *lim = (char *) sbrk (0); space_at_cmd_start = lim - lim_at_start; #endif } execute_command (command, instream == stdin); /* Set things up for this function to be compete later, once the execution has completed, if we are doing an execution command, otherwise, just go ahead and finish. */ if (target_can_async_p () && target_executing) { arg1 = (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); arg2 = (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); arg1->next = arg2; arg2->next = NULL; arg1->data.longint = time_at_cmd_start; #ifdef HAVE_SBRK arg2->data.longint = space_at_cmd_start; #endif add_continuation (command_line_handler_continuation, arg1); } /* Do any commands attached to breakpoint we stopped at. Only if we are always running synchronously. Or if we have just executed a command that doesn't start the target. */ if (!target_can_async_p () || !target_executing) { bpstat_do_actions (&stop_bpstat); do_cleanups (old_chain); if (display_time) { long cmd_time = get_run_time () - time_at_cmd_start; printf_unfiltered (_("Command execution time: %ld.%06ld\n"), cmd_time / 1000000, cmd_time % 1000000); } if (display_space) { #ifdef HAVE_SBRK char *lim = (char *) sbrk (0); long space_now = lim - lim_at_start; long space_diff = space_now - space_at_cmd_start; printf_unfiltered (_("Space used: %ld (%c%ld for this command)\n"), space_now, (space_diff >= 0 ? '+' : '-'), space_diff); #endif } } }
enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty) { struct cleanup *old_cleanups; char *run; char *async_args; if (target_can_async_p ()) { async_args = (char *) xmalloc (strlen (args) + 2); make_exec_cleanup (free, async_args); strcpy (async_args, args); strcat (async_args, "&"); run = xstrprintf ("%s %s", mi, async_args); make_exec_cleanup (free, run); add_continuation (mi_exec_async_cli_cmd_continuation, NULL); old_cleanups = NULL; } else { run = xstrprintf ("%s %s", mi, args); old_cleanups = make_cleanup (xfree, run); } if (!target_can_async_p ()) { /* NOTE: For synchronous targets asynchronous behavour is faked by printing out the GDB prompt before we even try to execute the command. */ if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^running\n", raw_stdout); fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); } else { /* FIXME: cagney/1999-11-29: Printing this message before calling execute_command is wrong. It should only be printed once gdb has confirmed that it really has managed to send a run command to the target. */ if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^running\n", raw_stdout); } execute_command ( /*ui */ run, 0 /*from_tty */ ); if (!target_can_async_p ()) { /* Do this before doing any printing. It would appear that some print code leaves garbage around in the buffer. */ do_cleanups (old_cleanups); /* If the target was doing the operation synchronously we fake the stopped message. */ if (last_async_command) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("*stopped", raw_stdout); mi_out_put (uiout, raw_stdout); mi_out_rewind (uiout); fputs_unfiltered ("\n", raw_stdout); return MI_CMD_QUIET; } return MI_CMD_DONE; }
/** * Append a new line of text at the end of the header. * A private copy of the text is made. * * @return an error code, or HEAD_OK if appending was successful. */ int header_append(header_t *o, const char *text, int len) { char buf[MAX_LINE_SIZE]; const char *p = text; uchar c; header_field_t *hf; header_check(o); g_assert(len >= 0); if (o->flags & HEAD_F_EOH) return HEAD_EOH_REACHED; /* * If empty line, we reached EOH. */ if (len == 0) { o->flags |= HEAD_F_EOH; /* Mark we reached EOH */ return HEAD_EOH; } /* * Sanity checks. */ if (o->size >= HEAD_MAX_SIZE) return HEAD_TOO_LARGE; if (++(o->num_lines) >= HEAD_MAX_LINES) return HEAD_MANY_LINES; /* * Detect whether line is a new header or a continuation. */ c = *p; if (is_ascii_space(c)) { /* * It's a continuation. * * Make sure we already have recorded something, or we have * an unexpected continuation line. */ if (NULL == o->fields) return HEAD_CONTINUATION; /* Unexpected continuation */ /* * When a previous header line was malformed, we cannot accept * further continuation lines. */ if (o->flags & HEAD_F_SKIP) return HEAD_SKIPPED; /* * We strip leading spaces of all continuations before storing * them. If we have to dump the header, we will have to put * some spaces, but we don't guarantee we'll put the same amount. */ p++; /* First char is known space */ while ((c = *p)) { if (!is_ascii_space(c)) break; p++; } /* * If we've reached the end of the line, then the continuation * line was made of spaces only. Weird, but we can ignore it. * Note that it's not an EOH mark. */ if (*p == '\0') return HEAD_OK; /* * Save the continuation line by appending into the last header * field we handled. */ hf = slist_tail(o->fields); hfield_append(hf, p); add_continuation(o, hf->name, p); o->size += len - (p - text); /* Count only effective text */ /* * Also append the data in the hash table. */ } else { char *b; bool seen_space = FALSE; /* * It's a new header line. */ o->flags &= ~HEAD_F_SKIP; /* Assume this line will be OK */ /* * Parse header field. Must be composed of ascii chars only. * (no control characters, no space, no ISO Latin or other extension). * The field name ends with ':', after possible white spaces. */ for (b = buf, c = *p; c; c = *(++p)) { if (c == ':') { *b++ = '\0'; /* Reached end of field */ break; /* Done, buf[] holds field name */ } if (is_ascii_space(c)) { seen_space = TRUE; /* Only trailing spaces allowed */ continue; } if ( seen_space || (c != '-' && c != '.' && (!isascii(c) || is_ascii_cntrl(c) || is_ascii_punct(c))) ) { o->flags |= HEAD_F_SKIP; return HEAD_BAD_CHARS; } *b++ = c; } /* * If buf[] does not end with a NUL, we did not fully recognize * the header: we reached the end of the line without encountering * the ':' marker. * * If the buffer starts with a NUL char, it's also clearly malformed. */ g_assert(b > buf || (b == buf && *text == '\0')); if (b == buf || *(b-1) != '\0') { o->flags |= HEAD_F_SKIP; return HEAD_MALFORMED; } /* * We have a valid header field in buf[]. */ hf = hfield_make(buf); /* * Strip leading spaces in the value. */ g_assert(*p == ':'); p++; /* First char is field separator */ p = skip_ascii_spaces(p); /* * Record field value. */ hfield_append(hf, p); add_header(o, buf, p); if (!o->fields) { o->fields = slist_new(); } slist_append(o->fields, hf); o->size += len - (p - text); /* Count only effective text */ } return HEAD_OK; }