wxString pgsRecord::value() const { wxString data; pgsVarMap vars; // Go through each line and enclose it into braces for (USHORT i = 0; i < count_lines(); i++) { data += wxT("("); // Go through each column and separate them with commas for (USHORT j = 0; j < count_columns(); j++) { wxString elm(m_record[i][j]->eval(vars)->value()); if (!m_record[i][j]->is_number()) { elm.Replace(wxT("\\"), wxT("\\\\")); elm.Replace(wxT("\""), wxT("\\\"")); elm = wxT("\"") + elm + wxT("\""); } data += elm + (j != count_columns() - 1 ? wxT(",") : wxT("")); } data += (i == count_lines() - 1) ? wxT(")") : wxT(")\n"); } // Return the string representation of the record return data; }
USHORT pgsRecord::get_column(wxString name) const { name = name.Strip(wxString::both).Lower(); if (name.IsEmpty()) { return count_columns(); } for (USHORT i = 0; i < count_columns(); i++) { if (m_columns[i] == name) return i; } return count_columns(); }
bool pgsRecord::newline() { // Insert a line m_record.Add(pgsVectorRecordLine()); // Initialize each column of the line with an empty string for (USHORT i = 0; i < count_columns(); i++) { m_record.Last().Add(pnew pgsString(wxT(""))); } return true; }
pgsOperand pgsRecord::get(const USHORT &line, const USHORT &column) const { if (line < count_lines() && column < count_columns()) { return m_record[line][column]; } else { return pnew pgsString(wxT("")); } }
pgsOperand pgsRecord::pgs_not() const { if (pgs_is_true()) { // A record with no line is false return pnew pgsRecord(count_columns()); } else { // A record with at least one line is true pgsRecord *copy = pnew pgsRecord(*this); copy->newline(); return copy; // Insert one line and return the record } }
pgsOperand pgsRecord::get_line(const USHORT &line) const { if (line < count_lines()) { pgsRecord *rec = pnew pgsRecord(count_columns()); rec->m_columns = this->m_columns; rec->newline(); rec->m_record[0] = this->m_record[line]; return rec; } else { return pnew pgsRecord(0); } }
bool pgsRecord::insert(const USHORT &line, const USHORT &column, pgsOperand value) { // Add lines to match the line number provided for (USHORT i = count_lines(); i <= line; i++) { newline(); } // Cannot insert if column is invalid if (column >= count_columns()) { return false; } // Insert the value at line.column else { m_record[line][column] = value; return true; } }
bool pgsRecord::set_column_name(const USHORT &column, wxString name) { // Column number must be valid if (column >= count_columns()) { return false; } // Column name must not exist // Column name must not be empty name = name.Strip(wxString::both).Lower(); if (m_columns.Index(name) != wxNOT_FOUND || name.IsEmpty()) { return false; } // Set the column name m_columns[column] = name; return true; }
int main(int argc, char **argv) { struct name_table_entry *name_table = typeCalloc(struct name_table_entry, CAPTABSIZE); HashValue *hash_table = typeCalloc(HashValue, HASHTABSIZE); const char *root_name = ""; int column = 0; int bigstring = 0; int n; char buffer[BUFSIZ]; static const char *typenames[] = {"BOOLEAN", "NUMBER", "STRING"}; short BoolCount = 0; short NumCount = 0; short StrCount = 0; /* The first argument is the column-number (starting with 0). * The second is the root name of the tables to generate. */ if (argc <= 3 || (column = atoi(argv[1])) <= 0 || (column >= MAX_COLUMNS) || *(root_name = argv[2]) == 0 || (bigstring = atoi(argv[3])) < 0 || name_table == 0 || hash_table == 0) { fprintf(stderr, "usage: make_hash column root_name bigstring\n"); exit(EXIT_FAILURE); } /* * Read the table into our arrays. */ for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { char **list, *nlp = strchr(buffer, '\n'); if (nlp) *nlp = '\0'; list = parse_columns(buffer); if (list == 0) /* blank or comment */ continue; if (column > count_columns(list)) { fprintf(stderr, "expected %d columns, have %d:\n%s\n", column, count_columns(list), buffer); exit(EXIT_FAILURE); } name_table[n].nte_link = -1; /* end-of-hash */ name_table[n].nte_name = strmalloc(list[column]); if (!strcmp(list[2], "bool")) { name_table[n].nte_type = BOOLEAN; name_table[n].nte_index = BoolCount++; } else if (!strcmp(list[2], "num")) { name_table[n].nte_type = NUMBER; name_table[n].nte_index = NumCount++; } else if (!strcmp(list[2], "str")) { name_table[n].nte_type = STRING; name_table[n].nte_index = StrCount++; } else { fprintf(stderr, "Unknown type: %s\n", list[2]); exit(EXIT_FAILURE); } n++; } _nc_make_hash_table(name_table, hash_table); /* * Write the compiled tables to standard output */ if (bigstring) { int len = 0; int nxt; printf("static const char %s_names_text[] = \\\n", root_name); for (n = 0; n < CAPTABSIZE; n++) { nxt = (int) strlen(name_table[n].nte_name) + 5; if (nxt + len > 72) { printf("\\\n"); len = 0; } printf("\"%s\\0\" ", name_table[n].nte_name); len += nxt; } printf(";\n\n"); len = 0; printf("static name_table_data const %s_names_data[] =\n", root_name); printf("{\n"); for (n = 0; n < CAPTABSIZE; n++) { printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", len, typenames[name_table[n].nte_type], name_table[n].nte_index, name_table[n].nte_link, n < CAPTABSIZE - 1 ? ',' : ' '); len += (int) strlen(name_table[n].nte_name) + 1; } printf("};\n\n"); printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); } else { printf("static struct name_table_entry const _nc_%s_table[] =\n", root_name); printf("{\n"); for (n = 0; n < CAPTABSIZE; n++) { _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "\"%s\"", name_table[n].nte_name); printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", buffer, typenames[name_table[n].nte_type], name_table[n].nte_index, name_table[n].nte_link, n < CAPTABSIZE - 1 ? ',' : ' '); } printf("};\n\n"); } printf("static const HashValue _nc_%s_hash_table[%d] =\n", root_name, HASHTABSIZE + 1); printf("{\n"); for (n = 0; n < HASHTABSIZE; n++) { printf("\t%3d,\n", hash_table[n]); } printf("\t0\t/* base-of-table */\n"); printf("};\n\n"); printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", BoolCount, NumCount, StrCount); printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); printf("#endif\n\n"); free(hash_table); return EXIT_SUCCESS; }
void print_comment () { register int column, format; enum codes comment_type; int start_column, found_column; int first_comment_line, right_margin; int boxed_comment, stars, blankline_delims, paragraph_break, merge_blank_comment_lines; int two_contiguous_comments = 0; int save_length = 0; char *save_ptr = 0; char *text_on_line = 0; char *line_break_ptr = 0; char *start_delim; char *line_preamble; int line_preamble_length, visible_preamble; int suppress_cdb = 0; /* GDB_HOOK_print_comment() */ /* Increment the parser stack, as we will store some things there for dump_line to use. */ inc_pstack (); /* Have to do it this way because this piece of shit program doesn't always place the last token code on the stack. */ if (*(token + 1) == '/') comment_type = cplus_comment; else comment_type = comment; /* First, decide what kind of comment this is: C++, C, or boxed C. Even if this appears to be a normal C comment, we may change our minds if we find a star in the right column of the second line, in which case that's a boxed comment too. */ if (comment_type == cplus_comment) { start_delim = "//"; line_preamble = "// "; line_preamble_length = 3; visible_preamble = 1; boxed_comment = 0; stars = 0; blankline_delims = 0; } else if (*buf_ptr == '*' || *buf_ptr == '-' || *buf_ptr == '=' || *buf_ptr == '_' || (parser_state_tos->col_1 && !format_col1_comments)) /* Boxed comment. This block of code will return. */ { int comment_lines_count = 1; found_column = start_column = current_column () - 2; parser_state_tos->box_com = 1; parser_state_tos->com_col = found_column; if (blanklines_before_blockcomments) prefix_blankline_requested = 1; *e_com++ = '/'; *e_com++ = '*'; while (1) { do { if (*buf_ptr == EOL) /* Count line numbers within comment blocks */ ++line_no; *e_com++ = *buf_ptr++; CHECK_COM_SIZE; } while (*buf_ptr != '*' && buf_ptr < buf_end); /* We have reached the end of the comment, and it's all on this line. */ if (*buf_ptr == '*' && *(buf_ptr + 1) == '/') { if (buf_ptr == buf_end) fill_buffer (); buf_ptr += 2; if (buf_ptr == buf_end) fill_buffer (); *e_com++ = '*'; *e_com++ = '/'; *e_com = '\0'; parser_state_tos->tos--; /* If this is the only line of a boxed comment, it may be after some other text (e.g., #if foo <comment>), in which case we want to specify the correct column. In the other cases, the leading spaces account for the columns and we start it in column 1. */ if (comment_lines_count > 1) parser_state_tos->com_col = 1; else parser_state_tos->com_col = found_column; return; } /* End of the line, or end of file. */ if (buf_ptr == buf_end) { if (*(buf_ptr - 1) == EOL) { *(--e_com) = '\0'; dump_line (true); comment_lines_count++; parser_state_tos->com_col = 1; } fill_buffer (); if (had_eof) { *e_com++ = '\0'; parser_state_tos->tos--; parser_state_tos->com_col = start_column; return; } } } } else { start_delim = "/*"; line_preamble = 0; line_preamble_length = 0; visible_preamble = 0; boxed_comment = 0; stars = star_comment_cont; blankline_delims = comment_delimiter_on_blankline; } paragraph_break = 0; merge_blank_comment_lines = 0; first_comment_line = com_lines; right_margin = comment_max_col; /* Now, compute the correct indentation for this comment and whether or not it should be formatted. */ found_column = current_column () - 2; if ((s_lab == e_lab) && (s_code == e_code)) /* First handle comments which begin the line. */ { if (parser_state_tos->col_1 && !format_col1_comments) { format = format_col1_comments; start_column = 1; } else if (s_com != e_com) /* The fool has a line consisting of two contiguous comments. In this case, we don't try too hard, 'cause nothing will look good. */ { format = 0; start_column = found_column; two_contiguous_comments = 1; } else { format = format_comments; if (parser_state_tos->ind_level <= 0 && (!parser_state_tos->in_stmt || (parser_state_tos->in_decl && parser_state_tos->paren_level == 0))) start_column = found_column; else /* This comment is within a procedure or other code. */ { start_column = compute_code_target () - unindent_displace; if (start_column < 0) start_column = 1; } } } else /* This comment follows code of some sort. */ { int target; suppress_cdb = 1; /* First, compute where the comment SHOULD go. */ if (parser_state_tos->decl_on_line) target = decl_com_ind; else if (else_or_endif) target = else_endif_col; else target = com_ind; /* Now determine if the code on the line is short enough to allow the comment to begin where it should. */ if (s_code != e_code) start_column = count_columns (compute_code_target (), s_code, NULL_CHAR); else /* s_lab != e_lab : there is a label here. */ start_column = count_columns (compute_label_target (), s_lab, NULL_CHAR); if (start_column < target) start_column = target; else { /* If the too-long code is a pre-processor command, start the comment 1 space afterwards, otherwise start at the next tab mark. */ if (else_or_endif) { start_column++; else_or_endif = false; } else start_column += tabsize - ((start_column - 1) % tabsize); } format = format_comments; } if (!line_preamble) { line_preamble_length = 3; if (stars) { line_preamble = " * "; visible_preamble = 1; } else { line_preamble = " "; visible_preamble = 0; } } /* These are the parser stack variables used to communicate formatting information to dump_line (). */ parser_state_tos->com_col = (two_contiguous_comments ? 1 : start_column); parser_state_tos->box_com = boxed_comment; /* Output the beginning comment delimiter. They are both two characters long. */ *e_com++ = *start_delim; *e_com++ = *(start_delim + 1); column = start_column + 2; /* If the user specified -cdb, put the delimiter on one line. */ if (blankline_delims && !suppress_cdb) { char *p = buf_ptr; *e_com = '\0'; dump_line (true); /* Check if the delimiter was already on a line by itself, and skip whitespace if formating. */ while (*p == ' ' || *p == TAB) p++; if (*p == EOL) buf_ptr = p + 1; else if (format) buf_ptr = p; if (buf_ptr >= buf_end) fill_buffer (); column = start_column; goto begin_line; } else if (format) { *e_com++ = ' '; column = start_column + 3; while (*buf_ptr == ' ' || *buf_ptr == TAB) if (++buf_ptr >= buf_end) fill_buffer (); } /* Iterate through the lines of the comment */ while (!had_eof) { /* Iterate through the characters on one line */ while (!had_eof) { CHECK_COM_SIZE; switch (*buf_ptr) { case ' ': case TAB: /* If formatting, and previous break marker is nonexistant, or before text on line, reset it to here. */ if (format && line_break_ptr < text_on_line) line_break_ptr = e_com; if (format) { /* Don't write two spaces after another, unless the first space it preceeded by a dot. */ if (e_com == s_com || e_com[-1] != ' ' || e_com - 1 == s_com || e_com[-2] == '.') { *e_com++ = ' '; column++; } } else if (*buf_ptr == ' ') { *e_com++ = ' '; column++; } else { /* Convert the tab to the appropriate number of spaces, based on the column we found the comment in, not the one we're printing in. */ int tab_width = (tabsize - ((column + found_column - start_column - 1) % tabsize)); column += tab_width; while (tab_width--) *e_com++ = ' '; } break; case EOL: /* We may be at the end of a C++ comment */ if (comment_type == cplus_comment) { cplus_exit: parser_state_tos->tos--; parser_state_tos->com_col = (two_contiguous_comments ? 1 : start_column); parser_state_tos->box_com = boxed_comment; *e_com = 0; return; } if (format) { /* Newline and null are the two characters which end an input line, so check here if we need to get the next line. */ if (*buf_ptr == EOL) ++line_no; buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); /* If there are any spaces between the text and this newline character, remove them. */ if (e_com > line_break_ptr && text_on_line < line_break_ptr) e_com = line_break_ptr; /* If this is "\n\n", or "\n<whitespace>\n", it's a paragraph break. */ while (*buf_ptr == TAB || *buf_ptr == ' ') if (++buf_ptr >= buf_end) fill_buffer (); if (*buf_ptr == EOL || !text_on_line) { paragraph_break = 1; goto end_line; } /* Also need to eat the preamble. */ if (!boxed_comment && current_column () == found_column + 1 && buf_ptr[0] == '*' && buf_ptr[1] != '/') { if (++buf_ptr >= buf_end) fill_buffer (); if (*buf_ptr == ' ' && ++buf_ptr >= buf_end) fill_buffer (); } /* This is a single newline. Transform it (and any following whitespace) into a single blank. */ if (e_com[-1] != ' ') { line_break_ptr = e_com; *e_com++ = ' '; column++; } continue; } /* We are printing this line "as is", so output it and continue on to the next line. */ goto end_line; case '*': /* Check if we've reached the end of the comment. */ if (comment_type == comment) { if (*(buf_ptr + 1) == '/') { /* If it's not a boxed comment, put some whitespace before the ending delimiter. Otherwise, simply insert the delimiter. */ if (!boxed_comment) { if (text_on_line) { if (blankline_delims && !suppress_cdb) { *e_com = '\0'; dump_line (true); *e_com++ = ' '; } else /* Insert space before closing delim */ if (*(e_com - 1) != ' ' && *(e_com - 1) != TAB) *e_com++ = ' '; } /* If no text on line, then line is completely empty or starts with preamble, or is beginning of comment and starts with beginning delimiter. */ else if (s_com == e_com || *s_com != '/') { e_com = s_com; *e_com++ = ' '; } else /* This is case of first comment line. Test with: if (first_comment_line != com_lines) abort (); */ if (*(e_com - 1) != ' ' && *(e_com - 1) != TAB) *e_com++ = ' '; } /* Now insert the ending delimiter */ *e_com++ = '*'; *e_com++ = '/'; *e_com = '\0'; /* Skip any whitespace following the comment. If there is only whitespace after it, print the line. NOTE: We're not printing the line: TRY IT! */ buf_ptr += 2; while (*buf_ptr == ' ' || *buf_ptr == TAB) buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); parser_state_tos->tos--; parser_state_tos->com_col = (two_contiguous_comments ? 1 : start_column); parser_state_tos->box_com = boxed_comment; return; } /* If this star is on the second line of the comment in the same column as the star of the beginning delimiter, then consider it a boxed comment. */ if (first_comment_line == com_lines - 1 && e_com == s_com + line_preamble_length && current_column () == found_column + 1) { /* Account for change in line_preamble_length: */ column -= line_preamble_length - 1; line_preamble = " "; line_preamble_length = 1; boxed_comment = 1; format = 0; blankline_delims = 0; *s_com = ' '; *(s_com + 1) = '*'; text_on_line = e_com = s_com + 2; column++; break; } } /* If it was not the end of the comment, drop through and insert the star on the line. */ default: /* Some textual character. */ text_on_line = e_com; *e_com++ = *buf_ptr; column++; break; } /* If we are formatting, check that we haven't exceeded the line length. If we haven't set line_break_ptr, keep going. */ if (format && column > right_margin && line_break_ptr) { if (line_break_ptr < e_com - 1) /* Here if we are really "breaking" the line: the line break is before some text we've seen. */ { *line_break_ptr = '\0'; save_ptr = line_break_ptr + 1; save_length = e_com - save_ptr; e_com = line_break_ptr; /* If we had to go past `right_margin' to print stuff out, extend `right_margin' out to this point. */ if ((column - save_length) > right_margin) right_margin = column - save_length; } else /* The line break is after the last text; we're really truncating the line. */ { if (comment_type == cplus_comment) { while (*buf_ptr == TAB || *buf_ptr == ' ') buf_ptr++; buf_ptr--; if (*buf_ptr == EOL) goto cplus_exit; } else { while (*buf_ptr == TAB || *buf_ptr == ' ' || *buf_ptr == EOL) buf_ptr++; buf_ptr--; } *e_com = '\0'; } goto end_line; } if (*buf_ptr == EOL) ++line_no; buf_ptr++; if (buf_ptr == buf_end) fill_buffer (); } end_line: /* Compress pure whitespace lines into newlines. */ if (!text_on_line && !visible_preamble && !(first_comment_line == com_lines)) e_com = s_com; *e_com = '\0'; dump_line (true); /* We're in the middle of a C-comment, don't add blank lines! */ prefix_blankline_requested = 0; /* If formatting (paragraph_break is only used for formatted comments) and user wants blank lines merged, kill all white space after the "\n\n" indicating a paragraph break. */ if (paragraph_break) { if (merge_blank_comment_lines) while (*buf_ptr == EOL || *buf_ptr == ' ' || *buf_ptr == TAB) { if (*buf_ptr == EOL) ++line_no; if (++buf_ptr >= buf_end) fill_buffer (); } paragraph_break = 0; } else { /* If it was a paragraph break (`if' clause), we scanned ahead one character. So, here in the `else' clause, advance buf_ptr. */ if (*buf_ptr == EOL) ++line_no; buf_ptr++; if (buf_ptr >= buf_end) fill_buffer (); } begin_line: if (had_eof) break; /* Indent the line properly. If it's a boxed comment, align with the '*' in the beginning slash-star and start inserting there. Otherwise, insert blanks for alignment, or a star if the user specified -sc. */ if (line_preamble) { (void) memcpy (e_com, line_preamble, line_preamble_length); e_com += line_preamble_length; column = start_column + line_preamble_length; } else column = start_column; line_break_ptr = 0; /* If we have broken the line before the end for formatting, copy the text after the break onto the beginning of this new comment line. */ if (save_ptr) { while ((*save_ptr == ' ' || *save_ptr == TAB) && save_length) { save_ptr++; save_length--; } (void) memcpy (e_com, save_ptr, save_length); text_on_line = e_com; e_com += save_length; /* We only break if formatting, in which cases there are no tabs, only spaces. */ column += save_length; save_ptr = 0; save_length = 0; } else { while (*buf_ptr == ' ' || *buf_ptr == TAB) if (++buf_ptr >= buf_end) fill_buffer (); text_on_line = 0; } } parser_state_tos->tos--; parser_state_tos->com_col = (two_contiguous_comments ? 1 : start_column); parser_state_tos->box_com = boxed_comment; }
/* table_log() trigger function for logging table changes parameter: - log table name (optional) return: - trigger data (for Pg) */ Datum table_log(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; int ret; char query[250 + NAMEDATALEN]; /* for getting table infos (250 chars (+ one times the length of all names) should be enough) */ int number_columns = 0; /* counts the number columns in the table */ int number_columns_log = 0; /* counts the number columns in the table */ char *orig_schema; char *log_schema; char *log_table; int use_session_user = 0; /* should we write the current (session) user to the log table? */ /* * Some checks first... */ #ifdef TABLE_LOG_DEBUG elog(NOTICE, "start table_log()"); #endif /* TABLE_LOG_DEBUG */ /* called by trigger manager? */ if (!CALLED_AS_TRIGGER(fcinfo)) { elog(ERROR, "table_log: not fired by trigger manager"); } /* must only be called for ROW trigger */ if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) { elog(ERROR, "table_log: can't process STATEMENT events"); } /* must only be called AFTER */ if (TRIGGER_FIRED_BEFORE(trigdata->tg_event)) { elog(ERROR, "table_log: must be fired after event"); } /* now connect to SPI manager */ ret = SPI_connect(); if (ret != SPI_OK_CONNECT) { elog(ERROR, "table_log: SPI_connect returned %d", ret); } /* get schema name for the table, in case we need it later */ orig_schema = get_namespace_name(RelationGetNamespace(trigdata->tg_relation)); #ifdef TABLE_LOG_DEBUG elog(NOTICE, "prechecks done, now getting original table attributes"); #endif /* TABLE_LOG_DEBUG */ number_columns = count_columns(trigdata->tg_relation->rd_att); if (number_columns < 1) { elog(ERROR, "table_log: number of columns in table is < 1, can this happen?"); } #ifdef TABLE_LOG_DEBUG elog(NOTICE, "number columns in orig table: %i", number_columns); #endif /* TABLE_LOG_DEBUG */ if (trigdata->tg_trigger->tgnargs > 3) { elog(ERROR, "table_log: too many arguments to trigger"); } /* name of the log schema */ if (trigdata->tg_trigger->tgnargs > 2) { /* check if a log schema argument is given, if yes, use it */ log_schema = trigdata->tg_trigger->tgargs[2]; } else { /* if no, use orig_schema */ log_schema = orig_schema; } /* should we write the current user? */ if (trigdata->tg_trigger->tgnargs > 1) { /* check if a second argument is given */ /* if yes, use it, if it is true */ if (atoi(trigdata->tg_trigger->tgargs[1]) == 1) { use_session_user = 1; #ifdef TABLE_LOG_DEBUG elog(NOTICE, "will write session user to 'trigger_user'"); #endif /* TABLE_LOG_DEBUG */ } } /* name of the log table */ if (trigdata->tg_trigger->tgnargs > 0) { /* check if a logtable argument is given */ /* if yes, use it */ log_table = (char *) palloc((strlen(trigdata->tg_trigger->tgargs[0]) + 2) * sizeof(char)); sprintf(log_table, "%s", trigdata->tg_trigger->tgargs[0]); } else { /* if no, use 'table name' + '_log' */ log_table = (char *) palloc((strlen(do_quote_ident(SPI_getrelname(trigdata->tg_relation))) + 5) * sizeof(char)); sprintf(log_table, "%s_log", SPI_getrelname(trigdata->tg_relation)); } #ifdef TABLE_LOG_DEBUG elog(NOTICE, "log table: %s", log_table); #endif /* TABLE_LOG_DEBUG */ #ifdef TABLE_LOG_DEBUG elog(NOTICE, "now check, if log table exists"); #endif /* TABLE_LOG_DEBUG */ /* get the number columns in the table */ snprintf(query, 249, "%s.%s", do_quote_ident(log_schema), do_quote_ident(log_table)); number_columns_log = count_columns(RelationNameGetTupleDesc(query)); if (number_columns_log < 1) { elog(ERROR, "could not get number columns in relation %s", log_table); } #ifdef TABLE_LOG_DEBUG elog(NOTICE, "number columns in log table: %i", number_columns_log); #endif /* TABLE_LOG_DEBUG */ /* check if the logtable has 3 (or now 4) columns more than our table */ /* +1 if we should write the session user */ if (use_session_user == 0) { /* without session user */ if (number_columns_log != number_columns + 3 && number_columns_log != number_columns + 4) { elog(ERROR, "number colums in relation %s(%d) does not match columns in %s(%d)", SPI_getrelname(trigdata->tg_relation), number_columns, log_table, number_columns_log); } } else { /* with session user */ if (number_columns_log != number_columns + 3 + 1 && number_columns_log != number_columns + 4 + 1) { elog(ERROR, "number colums in relation %s does not match columns in %s", SPI_getrelname(trigdata->tg_relation), log_table); } } #ifdef TABLE_LOG_DEBUG elog(NOTICE, "log table OK"); #endif /* TABLE_LOG_DEBUG */ /* For each column in key ... */ #ifdef TABLE_LOG_DEBUG elog(NOTICE, "copy data ..."); #endif /* TABLE_LOG_DEBUG */ if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) { /* trigger called from INSERT */ #ifdef TABLE_LOG_DEBUG elog(NOTICE, "mode: INSERT -> new"); #endif /* TABLE_LOG_DEBUG */ __table_log(trigdata, "INSERT", "new", trigdata->tg_trigtuple, number_columns, log_table, use_session_user, log_schema); } else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) { /* trigger called from UPDATE */ #ifdef TABLE_LOG_DEBUG elog(NOTICE, "mode: UPDATE -> old"); #endif /* TABLE_LOG_DEBUG */ __table_log(trigdata, "UPDATE", "old", trigdata->tg_trigtuple, number_columns, log_table, use_session_user, log_schema); #ifdef TABLE_LOG_DEBUG elog(NOTICE, "mode: UPDATE -> new"); #endif /* TABLE_LOG_DEBUG */ __table_log(trigdata, "UPDATE", "new", trigdata->tg_newtuple, number_columns, log_table, use_session_user, log_schema); } else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) { /* trigger called from DELETE */ #ifdef TABLE_LOG_DEBUG elog(NOTICE, "mode: DELETE -> old"); #endif /* TABLE_LOG_DEBUG */ __table_log(trigdata, "DELETE", "old", trigdata->tg_trigtuple, number_columns, log_table, use_session_user, log_schema); } else { elog(ERROR, "trigger fired by unknown event"); } #ifdef TABLE_LOG_DEBUG elog(NOTICE, "cleanup, trigger done"); #endif /* TABLE_LOG_DEBUG */ /* clean up */ pfree(log_table); /* close SPI connection */ SPI_finish(); /* return trigger data */ return PointerGetDatum(trigdata->tg_trigtuple); }
int main(int argc, char* argv[]){ if(argc < 2){ std::cout << " Error: Invalid number of arguments to " << argv[0] << ". Expected 1, received " << argc-1 << ".\n"; help(argv[0]); return 1; } std::vector<int> skip_lines; bool use_column_names = false; int index = 2; int num_head_lines = 0; int last_skip_line = -9999; char delimiter = '\t'; while(index < argc){ if(strcmp(argv[index], "--names") == 0){ std::cout << " Using first line of data for column names\n"; use_column_names = true; } else if(strcmp(argv[index], "--header") == 0){ if(index + 1 >= argc){ std::cout << " Error! Missing required argument to '--header'!\n"; help(argv[0]); return 1; } num_head_lines = atoi(argv[++index]); std::cout << " Using file header of " << num_head_lines << " lines\n"; } else if(strcmp(argv[index], "--delimiter") == 0){ if(index + 1 >= argc){ std::cout << " Error! Missing required argument to '--delimiter'!\n"; help(argv[0]); return 1; } delimiter = (char)atoi(argv[++index]); std::cout << " Using column delimiter '" << delimiter << "'\n"; } else if(strcmp(argv[index], "--skip") == 0){ if(index + 1 >= argc){ std::cout << " Error! Missing required argument to '--skip'!\n"; help(argv[0]); return 1; } int num_lines_to_skip = atoi(argv[++index]); std::cout << " Skipping " << num_lines_to_skip << " lines in the data file\n"; if(index + num_lines_to_skip >= argc){ std::cout << " Error! Missing required argument to '--skip'!\n"; help(argv[0]); return 1; } int temp_line; for(int i = 0; i < num_lines_to_skip; i++){ temp_line = atoi(argv[++index]); skip_lines.push_back(temp_line); if(temp_line > last_skip_line){ last_skip_line = temp_line; } } } else{ std::cout << " Error! Unrecognized option '" << argv[index] << "'!\n"; help(argv[0]); return 1; } index++; } std::ifstream input_file(argv[1]); if(!input_file.good()){ std::cout << " Error: Failed to open input file " << argv[1] << std::endl; return 1; } std::string fname = get_name(argv[1]); TFile *output_file = new TFile((fname+".root").c_str(),"RECREATE"); if(!output_file->IsOpen()){ std::cout << " Error: Failed to open output file " << fname << ".root\n"; input_file.close(); output_file->Close(); return 1; } TTree *tree = new TTree("data","Raw2Root Tree"); int count = 0; int num_columns = 0; output_file->cd(); std::vector<std::string> names; std::vector<std::string> titles; std::string first_line; if(num_head_lines > 0){ for(int i = 0; i < num_head_lines; i++){ std::getline(input_file, first_line); if(input_file.eof() || !input_file.good()){ input_file.close(); output_file->Close(); return 1; } if(is_in(skip_lines, ++count)){ continue; } size_t index = first_line.find(delimiter); if(index != std::string::npos){ names.push_back(first_line.substr(0, index)); titles.push_back(first_line.substr(index+1)); } else{ std::stringstream stream; if(i < 9){ stream << "line00" << i+1; } else if(i < 99){ stream << "line0" << i+1; } else{ stream << "line" << i+1; } names.push_back(stream.str()); titles.push_back(first_line); } } } /*for(int i = 0; i < names.size(); i++){ char *cstr1 = new char[names[i].length()+1]; for(int j = 0; j < names[i].length(); j++){ cstr1[j] = names[i].at(j); //std::cout << names[i][j] << "\t" << cstr1[j] << std::endl; } cstr1[names[i].length()] = '\0'; std::cout << names[i].length() << "\t" << strlen(cstr1) << std::endl; printf("cstr1: %s\n", cstr1); char *cstr2 = new char[titles[i].length()+1]; for(int j = 0; j < titles[i].length(); j++){ cstr2[j] = titles[i][j]; } cstr2[titles[i].length()] = '\0'; delete[] cstr1; delete[] cstr2; }*/ // Get the number of columns std::getline(input_file, first_line); if(input_file.eof() || !input_file.good()){ input_file.close(); output_file->Close(); return 1; } std::vector<std::string> column_names; num_columns = count_columns(first_line, column_names, delimiter); std::cout << " Found " << num_columns << " columns of data\n"; std::string bname; float *vars = new float[num_columns]; for(int i = 0; i < num_columns; i++){ vars[i] = 0.0; } if(!use_column_names){ input_file.seekg(-first_line.size(), std::ios::cur); for(int i = 0; i < num_columns; i++){ std::stringstream stream; if(i < 10){ stream << "Col0" << i; } else{ stream << "Col" << i; } tree->Branch(stream.str().c_str(),&vars[i]); } } else{ // Extract column names from data for(int i = 0; i < num_columns; i++){ tree->Branch(column_names[i].c_str(),&vars[i]); } } while(true){ // Get a line of data if(count % 10000 == 0 && count != 0){ std::cout << " Line " << count << " of data file\n"; } if(count+1 <= last_skip_line && is_in(skip_lines, ++count)){ continue; } for(int i = 0; i < num_columns; i++){ input_file >> vars[i]; } if(input_file.eof() || !input_file.good()){ break; } // Fill all branches tree->Fill(); count++; } output_file->cd(); TNamed *named = new TNamed(); std::vector<std::string>::iterator iter1, iter2; for(iter1 = names.begin(), iter2 = titles.begin(); iter1 != names.end() && iter2 != titles.end(); iter1++, iter2++){ named->SetNameTitle(iter1->c_str(), iter2->c_str()); named->Write(); } tree->Write(); std::cout << " Found " << count << " entries in " << num_columns << " columns\n"; std::cout << " Generated file " << fname << ".root\n"; input_file.close(); output_file->Close(); delete[] vars; return 0; }
int parse_config(FILE *cnf, ode_model_parameters *omp, main_options *cnf_options){ /* This function parses the configuration file The configuration * file contains xml like expressions containing data, measurement * time points, etc. * We start by defining regular expressions for the field names * */ int D=0,U=0,C=0,F=0,T=0,N=0; int i,l; int n=10; // number of fields regex_t cpt[2*n]; // defines the patterns for the field names regex_t comment; int bsize=2048; char buffer[bsize]; gsl_matrix *reference_data; gsl_matrix *sd_reference_data; omp->data_is_relative=0; // assume data to be absolute char *var_value, *var_value_newline; //comments in file regcomp(&comment,"#|//|%",REG_EXTENDED); regcomp(&cpt[0],"\\[time\\]",REG_EXTENDED); regcomp(&cpt[1],"\\[reference_input\\]",REG_EXTENDED); regcomp(&cpt[2],"\\[reference_data\\]",REG_EXTENDED); regcomp(&cpt[3],"\\[sd_reference_data\\]",REG_EXTENDED); regcomp(&cpt[4],"\\[input\\]",REG_EXTENDED); regcomp(&cpt[5],"\\[data\\]",REG_EXTENDED); regcomp(&cpt[6],"\\[sd_data\\]",REG_EXTENDED); regcomp(&cpt[7],"\\[prior_mu\\]",REG_EXTENDED); regcomp(&cpt[8],"\\[prior_inv(erse)?_cov(ariance)?\\]",REG_EXTENDED); regcomp(&cpt[9],"\\[output\\]",REG_EXTENDED); regcomp(&cpt[n+0],"\\[/time\\]",REG_EXTENDED); regcomp(&cpt[n+1],"\\[/reference_input\\]",REG_EXTENDED); regcomp(&cpt[n+2],"\\[/reference_data\\]",REG_EXTENDED); regcomp(&cpt[n+3],"\\[/sd_reference_data\\]",REG_EXTENDED); regcomp(&cpt[n+4],"\\[/input\\]",REG_EXTENDED); regcomp(&cpt[n+5],"\\[/data\\]",REG_EXTENDED); regcomp(&cpt[n+6],"\\[/sd_data\\]",REG_EXTENDED); regcomp(&cpt[n+7],"\\[/prior_mu\\]",REG_EXTENDED); regcomp(&cpt[n+8],"\\[/prior_inv(erse)?_cov(ariance)?\\]",REG_EXTENDED); regcomp(&cpt[n+9],"\\[/output\\]",REG_EXTENDED); /* now that we have several regular expressions, we parse the file * once to get the problem size: D,P,F,U,C; then we allocate mamory * and parse the file a second time to read the data, inputs and so * forth. */ /* relevant interfaces: * count_rows(FILE *cnf, regex_t *end, regex_t *comment) * count_columns(const char *c) * read_columns(char *c, double *vector, const int length) * read_block(int rows, int columns, FILE *f, double *target, regex_t *comment) */ while (!feof(cnf)){ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); var_value=strchr(buffer,'='); // string looks like this: [var_name]=[var_value] if (var_value!=NULL) { // we have a variable definition var_value[0]='\0'; //mark the end of the variable name /*printf("var_name=%s\n",buffer); printf("var_value=%s\n",var_value+1); *printf("removing newline....\n"); */ var_value_newline=strchr(++var_value,'\n'); if (var_value_newline!=NULL) var_value_newline[0]='\0'; printf("# [cfg] {%s} ← {%s}\n",buffer,var_value); if (strcmp(cnf_options->output_file,"sample.dat")==0 && strcmp(buffer,"output")==0) strcpy(cnf_options->output_file,var_value); else if (cnf_options->sample_size<0 && strcmp(buffer,"sample_size")==0) cnf_options->sample_size=strtol(var_value,NULL,0); else if (cnf_options->target_acceptance<0 && strcmp(buffer,"acceptance")==0) cnf_options->target_acceptance=strtod(var_value,NULL); else if (cnf_options->initial_stepsize<0 && strcmp(buffer,"step_size")==0) cnf_options->initial_stepsize=strtod(var_value,NULL); else if (strcmp(buffer,"t0")==0) {omp->t0=strtod(var_value,NULL); printf("# t0 = %f\n",omp->t0);} } else { for (i=0;i<n;i++){ if (regexec(&cpt[i],buffer,0,NULL,0)==0){ /* printf("found match with regular expression %i.\n",i); */ /* printf(buffer); */ switch (i){ // counting columns and/or rows case 0: /*time*/ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); T=count_rows(cnf, &cpt[n+i], &comment); break; case 1: /* reference input */ omp->data_is_relative=1; printf("data is relative.\n"); break; case 4: /* inputs */ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); U=count_columns(buffer); C=count_rows(cnf, &cpt[n+i], &comment); // printf("# input field has %i lines. (%i experimental conditions)\n",l,C); break; case 5: /* data */ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); F=count_columns(buffer); l=count_rows(cnf, &cpt[n+i], &comment); printf("# data has %i (%i × %i) lines.\n",l,C,T); break; case 7: /* problem size */ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); D=count_rows(cnf, &cpt[n+i], &comment); break; case 9: /* output structure */ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); N=count_columns(buffer); F=count_rows(cnf, &cpt[n+i], &comment); }// switch break; }// if match }// for (regular expressions) }// while !EOF } printf("# file read once to determine the size of data and inputs.\n"); printf("# D=%i\tN=%i\tF=%i\tU=%i\tC=%i\tT=%i\n",D,N,F,U,C,T); omp->D=D; /* now we must allocate the necessary memory and fill it with values */ ode_model_parameters_alloc(omp, D, N, F, T, U, C); reference_data=gsl_matrix_alloc(T,F); sd_reference_data=gsl_matrix_alloc(T,F); printf("# memory allocated.\n"); /* we reset the FILE structure and parse again, now reading the * values. */ rewind(cnf); printf("# rewind.\n"); while (!feof(cnf)){ do fgets(buffer,bsize,cnf); while (regexec(&comment,buffer,0,NULL,0)==0); for (i=0;i<n;i++){ if ( regexec(&cpt[i],buffer,0,NULL,0)==0){ /* printf("found match with regular expression %i.\n",i); */ /* printf(buffer); */ switch (i){// reading the data case 0: /*time*/ read_block(T,1,cnf,omp->t->data,&comment); printf("# measurement time(s) read.\n"); break; case 1: /* reference input */ //printf("# reading reference input.\n"); read_block(1,U,cnf,omp->reference_u->data,&comment); printf("# reference input read.\n"); break; case 2: /* reference data */ read_block(T,F,cnf,reference_data->data,&comment); printf("# reference data read.\n"); break; case 3: /* sd reference data */ read_block(T,F,cnf,sd_reference_data->data,&comment); printf("# standard deviation of reference data read.\n"); break; case 4: /* inputs */ read_block(C,U,cnf,omp->input_u->data,&comment); printf("# input read.\n"); break; case 5: /* data */ read_block(C*T,F,cnf,omp->Data->data,&comment); printf("# data read.\n"); break; case 6: /* sd data */ read_block(C*T,F,cnf,omp->sdData->data,&comment); printf("# standard deviation of data read.\n"); break; case 7: read_block(D,1,cnf,omp->prior_mu->data,&comment); printf("# prior mean read.\n"); break; case 8: /* prior inverse covariance */ read_block(D,D,cnf,omp->prior_inverse_cov->data,&comment); printf("# prior inverse covariance matrix read.\n"); break; case 9: /* output structure */ read_block(F,N,cnf,omp->output_C->data,&comment); }// switch break; }// if match }// for (regular expressions) }// while !EOF printf("# configuration read.\n"); /* now we take the ratios of data and reference data */ if (omp->data_is_relative){ printf("# calculating relative data (ratios)..."); ratio_with_sd(omp->Data,omp->sdData,reference_data,sd_reference_data); printf("# done.\n"); } // omp->t0=0.0; // cleanup gsl_matrix_free(reference_data); gsl_matrix_free(sd_reference_data); for (i=0;i<2*n;i++) regfree(&cpt[i]); return EXIT_SUCCESS; }