SEXP C_collapse_array_pretty_outer(SEXP x, SEXP indent) { if (!isString(x)) error("x must character vector."); int len = length(x); int ni = asInteger(indent); if(ni == NA_INTEGER) error("indent must not be NA"); //calculate required space size_t nchar_total = 0; for (int i=0; i<len; i++) { nchar_total += strlen(translateCharUTF8(STRING_ELT(x, i))); } //for indent plus two extra spaces plus ",\n" nchar_total += len * (ni + 4); //outer parentheses plus final indent and linebreak and terminator nchar_total += ni + 4; //allocate memory and create a cursor char *str = malloc(nchar_total); char *cursor = str; char **cur = &cursor; //init object append_text(cur, "[", 1); const char *start = *cur; //copy everything for (int i=0; i<len; i++) { append_text(cur, "\n", 1); append_whitespace(cur, ni + 2); append_text(cur, translateCharUTF8(STRING_ELT(x, i)), -1); append_text(cur, ",", 1); } //remove trailing ", " if(cursor != start){ cursor[-1] = '\n'; append_whitespace(cur, ni); } //finish up append_text(cur, "]\0", 2); //encode as UTF8 string SEXP out = PROTECT(allocVector(STRSXP, 1)); SET_STRING_ELT(out, 0, mkCharCE(str, CE_UTF8)); UNPROTECT(1); free(str); return out; }
void run_code_event(struct state *state, struct event *event, const char *text) { DEBUGP("%d: run code event\n", event->line_number); char *error = NULL; /* Wait for the right time before firing off this event. */ wait_for_event(state); //TODO modify to support multi socket support /* * Idea: extend event struct to put a socked_fd and get this fd from * the script (thus specified by user)? * */ if (state->socket_under_test == NULL) { asprintf(&error, "no socket to use for code"); goto error_out; } int fd = state->socket_under_test->live.fd; struct code_state *code = state->code; void *data = NULL; int data_len = 0; if (code->data_type == DATA_NONE) { /* First time: try various getsockopt calls until one works. */ #if HAVE_TCP_INFO if (data == NULL) { code->data_type = DATA_TCP_INFO; data = get_data(fd, code->data_type, &data_len); } #endif /* HAVE_TCP_INFO */ if (data == NULL) { asprintf(&error, "can't find getsockopt to get TCP info"); goto error_out; } } else { /* Run the getsockopt we already picked above. */ data = get_data(fd, code->data_type, &data_len); if (!data) { asprintf(&error, "can't get info for socket"); goto error_out; } } assert(code->data_type != DATA_NONE); assert(data != NULL); append_data(code, code->data_type, data, data_len); append_text(code, state->config->script_path, event->line_number, strdup(text)); return; error_out: die("%s:%d: runtime error in code: %s\n", state->config->script_path, event->line_number, error); free(error); }
SEXP C_collapse_array_pretty_inner(SEXP x) { if (!isString(x)) error("x must character vector."); //calculate required space int len = length(x); size_t nchar_total = 0; for (int i=0; i<len; i++) { nchar_total += strlen(translateCharUTF8(STRING_ELT(x, i))); } // n-1 ", " separators nchar_total += (len-1)*2; //outer parentheses plus terminator nchar_total += 3; //allocate memory and create a cursor char *str = malloc(nchar_total); char *cursor = str; char **cur = &cursor; //init object append_text(cur, "[", 1); //copy everything for (int i=0; i<len; i++) { append_text(cur, translateCharUTF8(STRING_ELT(x, i)), -1); append_text(cur, ", ", 2); } //remove trailing ", " if(len) { cursor -= 2; } //finish up append_text(cur, "]\0", 2); //encode as UTF8 string SEXP out = PROTECT(allocVector(STRSXP, 1)); SET_STRING_ELT(out, 0, mkCharCE(str, CE_UTF8)); UNPROTECT(1); free(str); return out; }
void ReplWindow::evaluate(Glib::ustring &expression) { Scheme *scm = Application::get()->get_scheme(); if (!expression.empty()) { const char *errmsg; s7_pointer old_port, result; int gc_loc = -1; // // Open a port to catch error info // old_port = s7_set_current_error_port(scm, s7_open_output_string(scm)); if (old_port != s7_nil(scm)) { gc_loc = s7_gc_protect(scm, old_port); } result = s7_eval_c_string(scm, expression.data()); errmsg = s7_get_output_string(scm, s7_current_error_port(scm)); append_text( "\n" ); if ((errmsg) && (*errmsg)) { append_text(errmsg); } else { char *result_as_string; result_as_string = s7_object_to_c_string(scm, result); if (result_as_string) { append_text(result_as_string); free(result_as_string); } } s7_close_output_port(scm, s7_current_error_port(scm)); s7_set_current_error_port(scm, old_port); if (gc_loc != -1) s7_gc_unprotect_at(scm, gc_loc); } }
static int append_short_backtrace(struct strbuf *result, problem_data_t *problem_data, size_t max_text_size, bool print_item_name) { const problem_item *item = problem_data_get_item_or_NULL(problem_data, FILENAME_BACKTRACE); if (!item) return 0; /* "I did not print anything" */ if (!(item->flags & CD_FLAG_TXT)) return 0; /* "I did not print anything" */ char *truncated = NULL; if (strlen(item->content) >= max_text_size) { struct sr_location location; sr_location_init(&location); /* sr_gdb_stacktrace_parse modifies the input parameter */ char *content = item->content; struct sr_gdb_stacktrace *backtrace = sr_gdb_stacktrace_parse((const char **)&content, &location); if (!backtrace) { log(_("Can't parse backtrace")); return 0; } /* Get optimized thread stack trace for 10 top most frames */ struct sr_gdb_thread *thread = sr_gdb_stacktrace_get_optimized_thread(backtrace, 10); sr_gdb_stacktrace_free(backtrace); if (!thread) { log(_("Can't find crash thread")); return 0; } /* Cannot be NULL, it dies on memory error */ struct sr_strbuf *bt = sr_strbuf_new(); sr_gdb_thread_append_to_str(thread, bt, true); sr_gdb_thread_free(thread); truncated = sr_strbuf_free_nobuf(bt); } append_text(result, /*item_name:*/ truncated ? "truncated_backtrace" : FILENAME_BACKTRACE, /*content:*/ truncated ? truncated : item->content, print_item_name ); free(truncated); return 1; }
/* collapse a json object with n spaces */ SEXP C_collapse_object_pretty(SEXP x, SEXP y, SEXP indent) { if (!isString(x) || !isString(y)) error("x and y must character vectors."); int ni = asInteger(indent); if(ni == NA_INTEGER) error("indent must not be NA"); int len = length(x); if (len != length(y)) error("x and y must have same length."); //calculate required space size_t nchar_total = 0; for (int i=0; i<len; i++) { if(STRING_ELT(y, i) == NA_STRING) continue; nchar_total += strlen(translateCharUTF8(STRING_ELT(x, i))); nchar_total += strlen(translateCharUTF8(STRING_ELT(y, i))); nchar_total += ni + 6; //indent plus two extra spaces plus ": " and ",\n" } //final indent plus curly braces and linebreak and terminator nchar_total += (ni + 2 + 2); //allocate memory and create a cursor char *str = malloc(nchar_total); char *cursor = str; char **cur = &cursor; //init object append_text(cur, "{", 1); const char *start = *cur; //copy everything for (int i=0; i<len; i++) { if(STRING_ELT(y, i) == NA_STRING) continue; append_text(cur, "\n", 1); append_whitespace(cur, ni + 2); append_text(cur, translateCharUTF8(STRING_ELT(x, i)), -1); append_text(cur, ": ", 2); append_text(cur, translateCharUTF8(STRING_ELT(y, i)), -1); append_text(cur, ",", 1); } //finalize object if(cursor != start){ cursor[-1] = '\n'; append_whitespace(cur, ni); } append_text(cur, "}\0", 2); //encode as UTF8 string SEXP out = PROTECT(allocVector(STRSXP, 1)); SET_STRING_ELT(out, 0, mkCharCE(str, CE_UTF8)); UNPROTECT(1); free(str); return out; }
Gobby::EncodingSelector::EncodingSelector(): m_show_automatic(false) { set_row_separator_func( sigc::mem_fun(*this, &EncodingSelector::row_sep_func) ); const std::vector<std::string>& encodings = Encoding::get_encodings(); for(std::vector<std::string>::const_iterator iter = encodings.begin(); iter != encodings.end(); ++ iter) { append_text(*iter); } }
static int setup(char *filename, pmOptions *opts) { FILE *fp; size_t length; int sts = 0, ended = 0; if (filename) fp = fopen(filename, "r"); else fp = fdopen(STDIN_FILENO, "r"); if (!fp) { fprintf(stderr, "%s: cannot open %s for reading configuration\n", pmProgname, filename? filename : "<stdin>"); return -oserror(); } while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { lineno++; length = strlen(buffer); if (length > 0 && buffer[length-1] == '\n') buffer[--length] = '\0'; /* * Check for special command character (hash) - if found process * the few commands it can represent -> getopts/usage/end. * If we're finished already, we just tack the text on unchanged. * Otherwise, we must deal with regular long options/headers/text. */ if (ended) sts = append_text(opts, buffer, length); else if (buffer[0] == '#') sts = ended = command(opts, buffer + 1); else sts = options(opts, buffer, length); if (sts < 0) break; } fclose(fp); /* if not given a getopt string with short options, just make one */ if (sts >= 0 && !opts->short_options) opts->short_options = build_short_options(opts); return sts; }
/*! * \brief * Callback for when new data is available in a pipe * * \param[in] source the event source * \param[in] condition the condition which has been satisfied * \param[in] data an unsigned integer as specified by #CHANNEL_ID, * converted to a \c gpointer using * \c GUINT_TO_POINTER() * * \return * \c FALSE when the event source should be removed, otherwise \c TRUE */ static gboolean io_watch_callback(GIOChannel *source, GIOCondition condition, gpointer data) { const guint8 input_type = GPOINTER_TO_UINT(data); gchar buffer[BUFFER_SIZE]; gsize bytes_read; GError *error = NULL; GIOStatus status; GIOChannel *write_to = NULL; if (IS_STDOUT(input_type)) { write_to = channel_stdin[1 ^ CLIENT_ID(input_type)]; } do { status = g_io_channel_read_chars(source, buffer, BUFFER_SIZE, &bytes_read, &error); if (error != NULL) { stop_channels(source, write_to); print_error(error->message); return FALSE; } if (bytes_read == 0) continue; if (write_to != NULL) { g_io_channel_write_chars(write_to, buffer, bytes_read, NULL, NULL); g_io_channel_flush(write_to, NULL); } append_text(buffer, bytes_read, input_type); } while (status == G_IO_STATUS_NORMAL); if ((condition & ~G_IO_IN) != 0) { stop_channels(source, write_to); return FALSE; } /* for some reason I can't figure out, this function is called repeatedly with condition==G_IO_IN when the client process ends - this check should prevent the program from becoming unresponsive and consuming 100% CPU */ return clients[CLIENT_ID(input_type)].is_running; }
gboolean markdown_textview_set_text(MarkdownTextView * self, const gchar * text) { gboolean result = TRUE; gchar **lines; gint line; g_return_val_if_fail(IS_MARKDOWN_TEXTVIEW(self), FALSE); markdown_textview_clear(self); lines = g_strsplit(text, "\n", 0); for (line = 0; result && lines[line]; line++) { result = append_text(self, (const gchar *)lines[line]); } g_strfreev(lines); load_images(self); return result; }
/** * Process a character token in cases where we expect only whitespace * * \param treebuilder The treebuilder instance * \param token The character token * \param insert_into_current_node Whether to insert whitespace into * current node * \return HUBBUB_REPROCESS if the token needs reprocessing * (token data updated to skip any leading whitespace), * HUBBUB_OK if it contained only whitespace, * appropriate error otherwise */ hubbub_error process_characters_expect_whitespace( hubbub_treebuilder *treebuilder, const hubbub_token *token, bool insert_into_current_node) { const uint8_t *data = token->data.character.ptr; size_t len = token->data.character.len; size_t c; for (c = 0; c < len; c++) { if (data[c] != 0x09 && data[c] != 0x0A && data[c] != 0x0C && data[c] != 0x20) break; } if (c > 0 && insert_into_current_node) { hubbub_error error; hubbub_string temp; temp.ptr = data; temp.len = c; error = append_text(treebuilder, &temp); if (error != HUBBUB_OK) return error; } /* Non-whitespace characters in token, so reprocess */ if (c != len) { /* Update token data to strip leading whitespace */ ((hubbub_token *) token)->data.character.ptr += c; ((hubbub_token *) token)->data.character.len -= c; return HUBBUB_REPROCESS; } return HUBBUB_OK; }
void CategorizeLine::CategorizeOneLine(ustring &line) { // Extract the marker for this line. ustring marker = usfm_extract_marker(line); // Marker to work with for this line. ustring actual_marker; if (marker.empty()) actual_marker = previous_marker; else actual_marker = marker; // Re-insert bible note markers. if (marker == footnote_opener(false)) { line.insert(0, footnote_opener(true)); } if (marker == endnote_opener(false)) { line.insert(0, endnote_opener(true)); } if (marker == xref_opener(false)) { line.insert(0, xref_opener(true)); } // Subdivide the line into categories. // Each category removes something from this content, until it is empty. // Footnotes, endnotes. if (!line.empty()) { size_t beginposition, endposition; ustring opening_marker = footnote_opener(true); ustring closing_marker = footnote_closer(); beginposition = line.find(opening_marker); endposition = line.find(closing_marker); if (endposition == string::npos) { // BUG: In main editor, the chapter lines are all combined into a single long ustring. // This means that footnotes that are split across lines are "fixed." But that is not // the case when just looking at a single verse \\v line that has a footnote started // but not finished. Fixed 2/15/2018 endposition = line.length() - 1; } while (beginposition != string::npos) { assert(beginposition <= endposition); // this cannot be above the while stmt...beginposition == string::npos if no marker is found ustring notetext; notetext = line.substr(beginposition + opening_marker.length(), endposition - beginposition - closing_marker.length()); line.erase(beginposition, endposition - beginposition + closing_marker.length()); clear_out_any_marker(notetext); append_text(note, notetext); beginposition = line.find(opening_marker); endposition = line.find(closing_marker); } opening_marker = endnote_opener(true); closing_marker = endnote_closer(); beginposition = line.find(opening_marker); endposition = line.find(closing_marker); while ((beginposition != string::npos) && (endposition != string::npos)) { ustring notetext; notetext = line.substr(beginposition + opening_marker.length(), endposition - beginposition - closing_marker.length()); line.erase(beginposition, endposition - beginposition + closing_marker.length()); clear_out_any_marker(notetext); append_text(note, notetext); beginposition = line.find(opening_marker); endposition = line.find(closing_marker); } } // Crossreferences. if (!line.empty()) { size_t beginposition, endposition; ustring opening_marker = xref_opener(true); ustring closing_marker = xref_closer(); beginposition = line.find(opening_marker); endposition = line.find(closing_marker); while ((beginposition != string::npos) && (endposition != string::npos)) { ustring referencetext; referencetext = line.substr(beginposition + opening_marker.length(), endposition - beginposition - closing_marker.length()); line.erase(beginposition, endposition - beginposition + closing_marker.length()); clear_out_any_marker(referencetext); append_text(ref, referencetext); beginposition = line.find(opening_marker); endposition = line.find(closing_marker); } } // Identifiers. if (!line.empty()) { if (is_id_marker(actual_marker)) { clear_out_any_marker(line); append_text(id, line); line.clear(); } } // Introduction elements. if (!line.empty()) { if (is_intro_marker(actual_marker)) { clear_out_any_marker(line); append_text(intro, line); line.clear(); } } // Headings, titles, labels. if (!line.empty()) { if (is_head_marker(actual_marker)) { clear_out_any_marker(line); append_text(head, line); line.clear(); } } // Chapter text. if (!line.empty()) { if (is_chap_marker(actual_marker)) { clear_out_any_marker(line); append_text(chap, line); line.clear(); } } // Extended study notes. As these use the existing footnote markers, // deal with the study notes first. if (!line.empty()) { if (is_study_marker(actual_marker)) { clear_out_any_marker(line); append_text(study, line); line.clear(); } } // After everything else has been removed, output the rest as main text. // This includes the "Verses" group, the "Paragraph Elements", and the // "Poetry Elements", the "Table Elements", and the "Special Text and // Character Styles", which have been filtered out already above. if (!line.empty()) { clear_out_any_marker(line); append_text(verse, line); line.clear(); } // Store previous marker. previous_marker = marker; }
/** * Handle tokens in "generic rcdata" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_generic_rcdata(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool done = false; if (treebuilder->context.strip_leading_lr && token->type != HUBBUB_TOKEN_CHARACTER) { /* Reset the LR stripping flag */ treebuilder->context.strip_leading_lr = false; } switch (token->type) { case HUBBUB_TOKEN_CHARACTER: { hubbub_string chars = token->data.character; if (treebuilder->context.strip_leading_lr) { if (chars.ptr[0] == '\n') { chars.ptr++; chars.len--; } treebuilder->context.strip_leading_lr = false; } if (chars.len == 0) break; err = append_text(treebuilder, &chars); } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type != treebuilder->context.collect.type) { /** \todo parse error */ } if ((treebuilder->context.enable_scripting == true) && (type == SCRIPT)) { err = complete_script(treebuilder); } done = true; } break; case HUBBUB_TOKEN_EOF: /** \todo if the current node's a script, * mark it as already executed */ /** \todo parse error */ done = true; err = HUBBUB_REPROCESS; break; case HUBBUB_TOKEN_COMMENT: case HUBBUB_TOKEN_DOCTYPE: case HUBBUB_TOKEN_START_TAG: /* Should never happen */ assert(0); break; } if (done) { hubbub_ns ns; element_type otype; void *node; /* Pop the current node from the stack */ element_stack_pop(treebuilder, &ns, &otype, &node); /* Return to previous insertion mode */ treebuilder->context.mode = treebuilder->context.collect.mode; } return err; }
static int append_item(struct strbuf *result, const char *item_name, problem_data_t *pd, GList *comment_fmt_spec) { bool print_item_name = (strncmp(item_name, "%bare_", strlen("%bare_")) != 0); if (!print_item_name) item_name += strlen("%bare_"); if (item_name[0] != '%') { struct problem_item *item = problem_data_get_item_or_NULL(pd, item_name); if (!item) return 0; /* "I did not print anything" */ if (!(item->flags & CD_FLAG_TXT)) return 0; /* "I did not print anything" */ char *formatted = problem_item_format(item); char *content = formatted ? formatted : item->content; append_text(result, item_name, content, print_item_name); free(formatted); return 1; /* "I printed something" */ } /* Special item name */ /* Compat with previously-existed ad-hockery: %short_backtrace */ if (strcmp(item_name, "%short_backtrace") == 0) return append_short_backtrace(result, pd, CD_TEXT_ATT_SIZE_BZ, print_item_name); /* Compat with previously-existed ad-hockery: %reporter */ if (strcmp(item_name, "%reporter") == 0) return append_text(result, "reporter", PACKAGE"-"VERSION, print_item_name); /* %oneline,%multiline,%text */ bool oneline = (strcmp(item_name+1, "oneline" ) == 0); bool multiline = (strcmp(item_name+1, "multiline") == 0); bool text = (strcmp(item_name+1, "text" ) == 0); if (!oneline && !multiline && !text) { log("Unknown or unsupported element specifier '%s'", item_name); return 0; /* "I did not print anything" */ } int printed = 0; /* Iterate over _sorted_ items */ GList *sorted_names = g_hash_table_get_keys(pd); sorted_names = g_list_sort(sorted_names, (GCompareFunc)strcmp); /* %text => do as if %oneline, then repeat as if %multiline */ if (text) oneline = 1; again: ; GList *l = sorted_names; while (l) { const char *name = l->data; l = l->next; struct problem_item *item = g_hash_table_lookup(pd, name); if (!item) continue; /* paranoia, won't happen */ if (!(item->flags & CD_FLAG_TXT)) continue; if (is_explicit_or_forbidden(name, comment_fmt_spec)) continue; char *formatted = problem_item_format(item); char *content = formatted ? formatted : item->content; char *eol = strchrnul(content, '\n'); bool is_oneline = (eol[0] == '\0' || eol[1] == '\0'); if (oneline == is_oneline) printed |= append_text(result, name, content, print_item_name); free(formatted); } if (text && oneline) { /* %text, and we just did %oneline. Repeat as if %multiline */ oneline = 0; /*multiline = 1; - not checked in fact, so why bother setting? */ goto again; } g_list_free(sorted_names); /* names themselves are not freed */ return printed; }
static int append_short_backtrace(struct strbuf *result, problem_data_t *problem_data, bool print_item_name, problem_report_settings_t *settings) { const problem_item *backtrace_item = problem_data_get_item_or_NULL(problem_data, FILENAME_BACKTRACE); const problem_item *core_stacktrace_item = NULL; if (!backtrace_item || !(backtrace_item->flags & CD_FLAG_TXT)) { backtrace_item = NULL; core_stacktrace_item = problem_data_get_item_or_NULL(problem_data, FILENAME_CORE_BACKTRACE); if (!core_stacktrace_item || !(core_stacktrace_item->flags & CD_FLAG_TXT)) return 0; } char *truncated = NULL; if (core_stacktrace_item || strlen(backtrace_item->content) >= settings->prs_shortbt_max_text_size) { log_debug("'backtrace' exceeds the text file size, going to append its short version"); char *error_msg = NULL; const char *type = problem_data_get_content_or_NULL(problem_data, FILENAME_TYPE); if (!type) { log_debug("Problem data does not contain '"FILENAME_TYPE"' file"); return 0; } /* For CCpp crashes, use the GDB-produced backtrace which should be * available by now. sr_abrt_type_from_type returns SR_REPORT_CORE * by default for CCpp crashes. */ enum sr_report_type report_type = sr_abrt_type_from_type(type); if (backtrace_item && strcmp(type, "CCpp") == 0) { log_debug("Successfully identified 'CCpp' abrt type"); report_type = SR_REPORT_GDB; } const char *content = backtrace_item ? backtrace_item->content : core_stacktrace_item->content; struct sr_stacktrace *backtrace = sr_stacktrace_parse(report_type, content, &error_msg); if (!backtrace) { log(_("Can't parse backtrace: %s"), error_msg); free(error_msg); return 0; } /* normalize */ struct sr_thread *thread = sr_stacktrace_find_crash_thread(backtrace); sr_thread_normalize(thread); /* Get optimized thread stack trace for max_frames top most frames */ truncated = sr_stacktrace_to_short_text(backtrace, settings->prs_shortbt_max_frames); sr_stacktrace_free(backtrace); if (!truncated) { log(_("Can't generate stacktrace description (no crash thread?)")); return 0; } } else { log_debug("'backtrace' is small enough to be included as is"); } /* full item content */ append_text(result, /*item_name:*/ truncated ? "truncated_backtrace" : FILENAME_BACKTRACE, /*content:*/ truncated ? truncated : backtrace_item->content, print_item_name ); free(truncated); return 1; }
static int options(pmOptions *opts, char *buffer, size_t length) { char *start, *finish, *token; pmLongOptions option = { 0 }; /* * Two cases to deal with here - a "standard" option e.g. --host * which is presented as a single word (no description) OR a full * description of a command line option, in one of these forms: * * --label dump the archive label * --background=COLOR render background with given color * -d, --desc get and print metric description * -b=N, --batch=N fetch N metrics at a time * -L use a local context connection * -X=N offset resulting values by N units */ if (pmDebug & DBG_TRACE_DESPERATE) fprintf(stderr, "%s: parsing option: '%s'", pmProgname, buffer); start = skip_whitespace(skip_nonwhitespace(buffer)); finish = skip_nonwhitespace(start); if (start[0] != '-') { *finish = '\0'; return append_text(opts, buffer, length); } token = skip_whitespace(finish); *finish = '\0'; /* if a single word, this is the standard PCP option case - find it */ if (!token || *token == '\0') return standard_options(opts, start); /* handle the first two example cases above -- long option only */ if (start[1] == '-') { token = seek_character(start, '='); if (*token == '=') { *token = '\0'; /* e.g. --background=COLOR render ... */ token++; finish = skip_nonwhitespace(token); *finish = '\0'; if ((option.argname = strdup(token)) == NULL) __pmNoMem("argname", strlen(token), PM_FATAL_ERR); option.has_arg = 1; } /* else e.g. --label dump the archive label */ if ((option.long_opt = strdup(start + 2)) == NULL) __pmNoMem("longopt", strlen(start), PM_FATAL_ERR); token = skip_whitespace(finish + 1); if ((option.message = strdup(token)) == NULL) __pmNoMem("message", strlen(token), PM_FATAL_ERR); return append_option(opts, &option); } /* handle next two example cases above -- both long and short options */ token = seek_character(start, ','); if (*token == ',') { /* e.g. -b=N, --batch=N fetch N metrics at a time */ option.short_opt = (int)start[1]; /* move onto extracting --batch, [=N], and "fetch..." */ token++; /* move past the comma */ if (*token == '\0' && token - buffer < length) /* move past a null */ token++; token = skip_whitespace(token); if ((token = seek_character(token, '-')) == NULL || (token - buffer >= length) || (token[1] != '-')) { fprintf(stderr, "%s: expected long option at \"%s\", line %d ignored\n", pmProgname, token, lineno); return -EINVAL; } start = token + 2; /* skip double-dash */ if ((token = seek_character(start, '=')) != NULL && *token == '=') { *token++ = '\0'; option.has_arg = 1; /* now extract the argument name */ finish = skip_nonwhitespace(token); *finish = '\0'; if ((option.argname = strdup(token)) == NULL) __pmNoMem("argname", strlen(token), PM_FATAL_ERR); } else { finish = skip_nonwhitespace(start); *finish = '\0'; } if ((option.long_opt = strdup(start)) == NULL) __pmNoMem("longopt", strlen(start), PM_FATAL_ERR); start = skip_whitespace(finish + 1); if ((option.message = strdup(start)) == NULL) __pmNoMem("message", strlen(start), PM_FATAL_ERR); return append_option(opts, &option); } /* handle final two example cases above -- short options only */ if (isspace(start[1])) { fprintf(stderr, "%s: expected short option at \"%s\", line %d ignored\n", pmProgname, start, lineno); return -EINVAL; } option.long_opt = ""; option.short_opt = start[1]; if ((token = seek_character(start, '=')) != NULL && *token == '=') { *token++ = '\0'; option.has_arg = 1; /* now extract the argument name */ finish = skip_nonwhitespace(token); *finish = '\0'; if ((option.argname = strdup(token)) == NULL) __pmNoMem("argname", strlen(token), PM_FATAL_ERR); /* e.g. -X=N offset resulting values by N units */ start = skip_whitespace(finish + 2); } else { /* e.g. -L use a local context connection */ start = skip_whitespace(start + 3); } if ((option.message = strdup(start)) == NULL) __pmNoMem("message", strlen(start), PM_FATAL_ERR); return append_option(opts, &option); }
void append_text( std::string& str, const FIRST& first, const REST&... rest ) { append_text( str, first ) ; append_text( str, rest...) ; }