/* Copyright (C) 2013-2019 Free Software Foundation, Inc. Written by Ron Norman, Simon Sobisch This file is part of GnuCOBOL. The GnuCOBOL runtime library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GnuCOBOL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GnuCOBOL. If not, see . */ #include #include #include #include #include #include #include /* Force symbol exports */ #define COB_LIB_EXPIMP #include "libcob.h" #include "coblocal.h" #ifdef WORDS_BIGENDIAN #define COB_MAYSWAP_16(x) ((unsigned short)(x)) #define COB_MAYSWAP_32(x) ((unsigned int)(x)) #else #define COB_MAYSWAP_16(x) (COB_BSWAP_16((unsigned short)(x))) #define COB_MAYSWAP_32(x) (COB_BSWAP_32((unsigned int)(x))) #endif static cob_global *cobglobptr= NULL; static cob_settings *cobsetptr= NULL; static int bDidReportInit = 0; #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define ND1 COB_REPORT_HEADING|COB_REPORT_FOOTING|COB_REPORT_PAGE_HEADING|COB_REPORT_PAGE_FOOTING #define ND2 COB_REPORT_CONTROL_HEADING|COB_REPORT_CONTROL_HEADING_FINAL #define ND3 COB_REPORT_CONTROL_FOOTING|COB_REPORT_CONTROL_FOOTING_FINAL #define NOTDETAIL(f) ( f & (ND1|ND2|ND3)) static int report_line_type(cob_report *r, cob_report_line *l, int type); static const cob_field_attr const_alpha_attr = {COB_TYPE_ALPHANUMERIC, 0, 0, 0, NULL}; static const cob_field_attr const_num_attr = {COB_TYPE_NUMERIC, 0, 0, 0, NULL}; #define MAX_ACTIVE_REPORTS 10 static cob_report *active_reports[MAX_ACTIVE_REPORTS]; /* * Move "String" to 'dst' field */ static void cob_str_move (cob_field *dst, unsigned char *src, const int size) { cob_field temp; temp.size = size; temp.data = src; temp.attr = &const_alpha_attr; cob_move (&temp, dst); } /* * Initialize data field */ static cob_field * cob_field_init (cob_field *f) { cob_field temp; if(f == NULL) return NULL; temp.size = 1; if(COB_FIELD_IS_NUMERIC(f)) { temp.data = (unsigned char*)"0"; /* MOVE ZERO to field */ temp.attr = &const_num_attr; } else { temp.data = (unsigned char*)" "; /* MOVE SPACES to field */ temp.attr = &const_alpha_attr; } cob_move (&temp, f); return f; } /* * Make a new field the same format as that given */ static cob_field * cob_field_dup (cob_field *f, int incr) { cob_field temp; cob_field *fld = cob_malloc(sizeof(cob_field)); size_t dsize = f->size + incr; fld->size = dsize; fld->data = cob_malloc((size_t)(dsize < COB_MAX_DIGITS ? COB_MAX_DIGITS : dsize) + 1); fld->attr = f->attr; temp.size = 1; if (COB_FIELD_IS_NUMERIC (f)) { temp.data = (unsigned char*)"0"; /* MOVE ZERO to new field */ temp.attr = &const_num_attr; } else { temp.data = (unsigned char*)" "; /* MOVE SPACES to new field */ temp.attr = &const_alpha_attr; } cob_move (&temp, fld); return fld; } /* * Free a field created by cob_field_dup */ static void cob_field_free (cob_field *f) { if(f == NULL) return; if(f->data) cob_free((void*)f->data); cob_free((void*)f); return ; } /* * Free control temp areas */ static void free_control_fields (cob_report *r) { cob_report_control *rc; cob_report_control_ref *rr; int k; for(rc = r->controls; rc; rc = rc->next) { if(rc->val) { cob_field_free(rc->val); rc->val = NULL; } if(rc->sf) { cob_field_free(rc->sf); rc->sf = NULL; } rc->has_heading = FALSE; rc->has_footing = FALSE; for(rr = rc->control_ref; rr; rr = rr->next) { if (rr->ref_line->flags & COB_REPORT_CONTROL_HEADING || rr->ref_line->flags & COB_REPORT_CONTROL_HEADING_FINAL) rc->has_heading = TRUE; if (rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING || rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING_FINAL) rc->has_footing = TRUE; } } for(k=0; k < MAX_ACTIVE_REPORTS; k++) { if (active_reports[k] == r) { active_reports[k] = NULL; } } } /* * Clear the 'group_indicate' flag for all fields */ static void clear_group_indicate(cob_report_line *l) { cob_report_field *f; for(f=l->fields; f; f=f->next) { f->group_indicate = FALSE; } if(l->child) clear_group_indicate(l->child); if(l->sister) clear_group_indicate(l->sister); } /* * Clear the 'suppress' flag for all fields */ static void clear_suppress(cob_report_line *l) { cob_report_field *f; l->suppress = FALSE; for(f=l->fields; f; f=f->next) { if((f->flags & COB_REPORT_GROUP_ITEM)) continue; f->suppress = FALSE; } if(l->child) clear_suppress(l->child); if(l->sister) clear_suppress(l->sister); } /* * Return control field sequence value for given report line * else return -1 */ static int get_control_sequence(cob_report *r, cob_report_line *l) { cob_report_control *c; cob_report_control_ref *rr; if(r->controls) { for(c=r->controls; c; c = c->next) { for(rr=c->control_ref; rr; rr=rr->next) { if(rr->ref_line == l) { return c->sequence; } } } } return -1; } /* * If this line has NEXT GROUP .... then set info in report header */ static void set_next_info(cob_report *r, cob_report_line *l) { if(l->flags & COB_REPORT_NEXT_GROUP_LINE) { r->next_value = l->next_group_line; r->next_line = TRUE; r->next_just_set = TRUE; r->next_line_plus = FALSE; DEBUG_LOG("rw",(" Save NEXT GROUP LINE %d\n",r->next_value)); } if(l->flags & COB_REPORT_NEXT_GROUP_PLUS) { r->next_value = l->next_group_line; r->next_line = FALSE; r->next_line_plus = TRUE; r->next_just_set = TRUE; DEBUG_LOG("rw",(" Save NEXT GROUP PLUS %d\n",r->next_value)); } if(l->flags & COB_REPORT_NEXT_GROUP_PAGE) { r->next_value = l->next_group_line; r->next_line = FALSE; r->next_page = TRUE; r->next_just_set = TRUE; DEBUG_LOG("rw",(" Save NEXT GROUP PAGE\n")); } } static cob_report_line * get_print_line(cob_report_line *l) { while(l && l->fields == NULL && l->child != NULL) l = l->child; /* Find line with data fields */ return l; } /* * Do any global initialization needed */ static void reportInitialize() { if(bDidReportInit) return; bDidReportInit = 1; } /* * Add Two Fields together giving Result */ static void cob_add_fields(cob_field *op1, cob_field *op2, cob_field *rslt) { cob_field_attr attr1, attr2; char data1[30],data2[30]; cob_field fld1,fld2; #ifdef COB_DEBUG_LOG char wrk[32]; #endif /* Copy data to local PIC 9 DISPLAY fields */ /* As cob_add does not handle NUMERIC_EDITED very well */ fld1.size = op1->size; attr1 = *op1->attr; fld1.attr = &attr1; attr1.type = COB_TYPE_NUMERIC_DISPLAY; fld1.data = (unsigned char*)data1; memset(data1,'0',fld1.size); cob_move(op1, &fld1); #ifdef COB_DEBUG_LOG if(DEBUG_ISON("rw")) { cob_field_to_string(op1, wrk, sizeof(wrk)-1); DEBUG_LOG("rw",(" Add '%s' ",wrk)); } #endif fld2.size = op2->size; attr2 = *op2->attr; fld2.attr = &attr2; attr2.type = COB_TYPE_NUMERIC_DISPLAY; fld2.data = (unsigned char*)data2; memset(data2,'0',fld2.size); cob_move(op2, &fld2); #ifdef COB_DEBUG_LOG if(DEBUG_ISON("rw")) { cob_field_to_string(op2, wrk, sizeof(wrk)-1); DEBUG_LOG("rw",("TO '%s' ",wrk)); } #endif cob_add(&fld1,&fld2,0); cob_move(&fld1, rslt); /* Copy SUM back to result field */ #ifdef COB_DEBUG_LOG if(DEBUG_ISON("rw")) { cob_field_to_string(&fld1, wrk, sizeof(wrk)-1); DEBUG_LOG("rw",("GIVING '%s' ",wrk)); DEBUG_LOG("rw",(" PIC 9(%d)",rslt->attr->digits)); if(rslt->attr->scale > 0) DEBUG_LOG("rw",("V9(%d)",rslt->attr->scale)); DEBUG_LOG("rw",("\n")); } #endif } #ifdef COB_DEBUG_LOG static void dumpFlags(int flags, int ln, char *name) { if (!DEBUG_ISON("rw")) { return; } if(name == NULL) name = (char*)""; if(flags & COB_REPORT_HEADING) DEBUG_LOG("rw",("REPORT HEADING ")); if(flags & COB_REPORT_FOOTING) DEBUG_LOG("rw",("REPORT FOOTING ")); if(flags & COB_REPORT_PAGE_HEADING) DEBUG_LOG("rw",("PAGE HEADING ")); if(flags & COB_REPORT_PAGE_FOOTING) DEBUG_LOG("rw",("PAGE FOOTING ")); if(flags & COB_REPORT_CONTROL_HEADING) DEBUG_LOG("rw",("CONTROL HEADING %s ",name)); if(flags & COB_REPORT_CONTROL_HEADING_FINAL) DEBUG_LOG("rw",("CONTROL HEADING FINAL ")); if(flags & COB_REPORT_CONTROL_FOOTING) { if(flags & COB_REPORT_ALL) DEBUG_LOG("rw",("CONTROL FOOTING %s ",name)); else DEBUG_LOG("rw",("CONTROL FOOTING ALL ")); } if(flags & COB_REPORT_CONTROL_FOOTING_FINAL) DEBUG_LOG("rw",("CONTROL FOOTING FINAL ")); if(flags & COB_REPORT_DETAIL) DEBUG_LOG("rw",("DETAIL ")); if(flags & COB_REPORT_LINE_PLUS) {if(ln > 0) DEBUG_LOG("rw",("LINE PLUS %d ",ln));} else if(flags & COB_REPORT_LINE) DEBUG_LOG("rw",("LINE %d ",ln)); if(flags & COB_REPORT_LINE_NEXT_PAGE) DEBUG_LOG("rw",("LINE NEXT PAGE ")); if(flags & COB_REPORT_NEXT_PAGE) DEBUG_LOG("rw",("NEXT PAGE ")); if(flags & COB_REPORT_GROUP_INDICATE) DEBUG_LOG("rw",("GROUP INDICATE ")); if(flags & COB_REPORT_COLUMN_PLUS) DEBUG_LOG("rw",("COLUMN PLUS ")); if(flags & COB_REPORT_RESET_FINAL) DEBUG_LOG("rw",("RESET FINAL ")); if(flags & COB_REPORT_COLUMN_LEFT) DEBUG_LOG("rw",("LEFT ")); if(flags & COB_REPORT_COLUMN_RIGHT) DEBUG_LOG("rw",("RIGHT ")); if(flags & COB_REPORT_COLUMN_CENTER) DEBUG_LOG("rw",("CENTER ")); if(flags & COB_REPORT_GROUP_ITEM) DEBUG_LOG("rw",("GROUP ")); if(flags & COB_REPORT_PRESENT) { if(flags & COB_REPORT_NEGATE) { if(flags & COB_REPORT_BEFORE) { DEBUG_LOG("rw",("ABSENT BEFORE ")); } else { DEBUG_LOG("rw",("ABSENT AFTER ")); } } else { if(flags & COB_REPORT_BEFORE) { DEBUG_LOG("rw",("PRESENT BEFORE ")); } else { DEBUG_LOG("rw",("PRESENT AFTER ")); } } if(flags & COB_REPORT_PAGE) DEBUG_LOG("rw",("PAGE ")); if(flags & COB_REPORT_ALL) DEBUG_LOG("rw",("ALL ")); } else if(flags & COB_REPORT_HAD_WHEN) DEBUG_LOG("rw",("WHEN ")); } #endif #ifdef COB_DEBUG_LOG static void reportDumpOneLine(const cob_report *r, cob_report_line *fl, int indent, int dumpdata) { cob_report_field *rf; cob_report_control *c; cob_report_control_ref *rr; cob_report_control *rc; int sequence = -1; char idnt[48], wrk[200]; if (!DEBUG_ISON("rw")) { return; } sprintf(idnt,"%.*s",indent>30?30:indent,".................................."); DEBUG_LOG("rw",("%s ",idnt)); if (dumpdata) { DEBUG_LOG("rw",("Line# %d of Page# %d; ",r->curr_line,r->curr_page)); } if (r->controls) { for(c=r->controls; c; c = c->next) { for(rr=c->control_ref; rr; rr=rr->next) { if(rr->ref_line == fl) { strcpy(wrk,c->name); sequence = c->sequence; break; } } } } dumpFlags(fl->report_flags,fl->line,wrk); if(fl->step_count) DEBUG_LOG("rw",("Step %3d ",fl->step_count)); if(fl->suppress) DEBUG_LOG("rw",("Suppress Line ")); if(fl->next_group_line) { DEBUG_LOG("rw",("NEXT ",fl->next_group_line)); if(fl->report_flags & COB_REPORT_NEXT_GROUP_LINE) DEBUG_LOG("rw",("GROUP LINE ")); if(fl->report_flags & COB_REPORT_NEXT_GROUP_PLUS) DEBUG_LOG("rw",("GROUP PLUS ")); if(fl->report_flags & COB_REPORT_NEXT_GROUP_PAGE) DEBUG_LOG("rw",("GROUP PAGE ")); DEBUG_LOG("rw",("%d ",fl->next_group_line)); } else { if(fl->report_flags & COB_REPORT_NEXT_GROUP_PAGE) DEBUG_LOG("rw",("NEXT GROUP PAGE ")); } if(fl->control) { cob_field_to_string(fl->control, wrk, sizeof(wrk)-1); if(wrk[0] >= ' ') DEBUG_LOG("rw",("Line Control %d is '%s' ",sequence,wrk)); } DEBUG_LOG("rw",("\n")); if(!(fl->flags & COB_REPORT_DETAIL)) dumpdata = 1; for(rf = fl->fields; rf; rf = rf->next) { DEBUG_LOG("rw",("%s %02d Field ",idnt,rf->level)); if(rf->line) DEBUG_LOG("rw",("Line %2d ",rf->line)); if(rf->column) DEBUG_LOG("rw",("Col %3d ",rf->column)); if(rf->step_count) DEBUG_LOG("rw",("Step %3d ",rf->step_count)); if(rf->next_group_line) DEBUG_LOG("rw",("NextGrp %d ",rf->next_group_line)); if(dumpdata) { if(!(rf->flags & COB_REPORT_GROUP_ITEM)) { if(rf->f) { if(rf->litval) { DEBUG_LOG("rw",(" \"%s\" ",rf->litval)); } else { cob_field_to_string(rf->f, wrk, sizeof(wrk)-1); DEBUG_LOG("rw",(" '%s' ",wrk)); } } } if(rf->source && cob_cmp(rf->f,rf->source) != 0) { if(rf->source == r->page_counter) { DEBUG_LOG("rw",("Source PAGE-COUNTER ")); } else if(rf->source == r->line_counter) { DEBUG_LOG("rw",("Source LINE-COUNTER ")); } } if((rf->flags & COB_REPORT_PRESENT) && !rf->present_now && r->initiate_done) { dumpFlags(rf->flags& ~(COB_REPORT_PRESENT|COB_REPORT_HAD_WHEN),rf->line,NULL); if((rf->flags & COB_REPORT_NEGATE)) DEBUG_LOG("rw",("ABSENT")); else DEBUG_LOG("rw",("Not PRESENT")); } else if((rf->flags & COB_REPORT_GROUP_ITEM) && rf->suppress) { dumpFlags(rf->flags& ~(COB_REPORT_GROUP_ITEM|COB_REPORT_HAD_WHEN),rf->line,NULL); DEBUG_LOG("rw",("Suppress group")); } else { dumpFlags(rf->flags,rf->line,NULL); } if(rf->control && (!(rf->flags & COB_REPORT_PRESENT) || rf->present_now || !r->initiate_done) ) { strcpy(wrk,""); for(rc = r->controls; rc; rc = rc->next) { if(rc->f == rf->control) { strcpy(wrk,rc->name); break; } } if(wrk[0] >= ' ') DEBUG_LOG("rw",("Control %s ",wrk)); } } if(!(rf->flags & COB_REPORT_GROUP_ITEM) && rf->suppress) DEBUG_LOG("rw",("Suppress field")); DEBUG_LOG("rw",("\n")); } } #endif #ifdef COB_DEBUG_LOG /* * Dump REPORT line and walk down tree */ static void reportDumpLine(const cob_report *r, cob_report_line *fl, int indent) { if(!DEBUG_ISON("rw")) return; reportDumpOneLine(r,fl,indent,0); if(fl->child) reportDumpLine(r,fl->child,indent+2); if(fl->sister) reportDumpLine(r,fl->sister,indent); } #endif #ifdef COB_DEBUG_LOG /* * Dump entire REPORT definition tables */ static void reportDump(const cob_report *r, const char *msg) { cob_report_control *c; char wrk[80]; if (!DEBUG_ISON("rw")) { return; } DEBUG_LOG("rw",("Dump of Report '%s' for %s\n",r->report_name,msg)); if (r->report_file) { DEBUG_LOG("rw",("Using File %s ",r->report_file->select_name)); if(r->report_file->assign && r->report_file->assign->data) { DEBUG_LOG("rw",(" ASSIGNed to %s",r->report_file->assign->data)); } DEBUG_LOG("rw",(" Rcsz min %d max %d ",r->report_file->record_min,r->report_file->record_max)); #if 0 /* * TODO: This needs more work. Cross check how fileio.c handles print files * and exactly what operations should be used */ if(r->report_file->flag_select_features & COB_SELECT_LINAGE) { DEBUG_LOG("rw",("has LINAGE")); } else { /* * Create LINAGE clause fields for fileio.c so that * the output file looks more like what Micro Focus would create */ cob_linage *lingptr; if(r->report_file->linorkeyptr == NULL) { r->report_file->linorkeyptr = cob_malloc(sizeof(cob_linage)); lingptr = r->report_file->linorkeyptr; lingptr->lin_top = r->def_heading; lingptr->lin_bot = r->def_footing; lingptr->linage = cob_field_dup(r->line_counter,0); lingptr->linage_ctr = cob_field_dup(r->line_counter,0); r->report_file->flag_select_features |= COB_SELECT_LINAGE; } DEBUG_LOG("rw",("had NO LINAGE!")); } #endif DEBUG_LOG("rw",("\n")); } DEBUG_LOG("rw",("\n")); DEBUG_LOG("rw",("Default Lines: %4d Columns: %4d\n",r->def_lines,r->def_cols)); DEBUG_LOG("rw",(" Heading: %4d Footing: %4d\n",r->def_heading,r->def_footing)); DEBUG_LOG("rw",(" Detail: %4d Control: %4d Last detail: %4d\n",r->def_first_detail, r->def_last_control,r->def_last_detail)); if((r->curr_page+r->curr_status+r->curr_line+r->curr_cols) > 0) { DEBUG_LOG("rw",("Current Page: %4d Status: %4d\n",r->curr_page,r->curr_status)); DEBUG_LOG("rw",(" Line: %4d Column: %4d\n",r->curr_line,r->curr_cols)); } DEBUG_LOG("rw",("\n")); if(r->controls) { for(c=r->controls; c; c = c->next) { DEBUG_LOG("rw",(" Control %s ",c->name)); if(c->f) { cob_field_to_string(c->f, wrk, sizeof(wrk)-1); if(wrk[0] >= ' ') DEBUG_LOG("rw",("has '%s' ",wrk)); } if(c->val) { cob_field_to_string(c->val, wrk, sizeof(wrk)-1); if(wrk[0] >= ' ') DEBUG_LOG("rw",("Value '%s' ",wrk)); } DEBUG_LOG("rw",("\n")); } } reportDumpLine(r,r->first_line,0); DEBUG_LOG("rw",("\n")); } #endif /* * Verify that each LINE # is within PAGE LIMITS */ static void limitCheckOneLine(cob_report *r, cob_report_line *fl) { cob_report_field *rf; if((fl->line > 0 && r->def_lines > 0 && fl->line > r->def_lines)) { cob_runtime_error (_("INITIATE %s LINE %d exceeds PAGE LIMIT %d"),r->report_name,fl->line,r->def_lines); DEBUG_LOG("rw",("PAGE LIMITs is incorrect; LINE %d > LIMIT %d\n",fl->line,r->def_lines)); cob_set_exception (COB_EC_REPORT_PAGE_LIMIT); r->initiate_done = FALSE; return; } if((fl->next_group_line > 0 && r->def_lines > 0 && fl->next_group_line > r->def_lines)) { cob_runtime_error (_("INITIATE %s NEXT GROUP %d exceeds PAGE LIMIT"),r->report_name,fl->next_group_line); DEBUG_LOG("rw",("PAGE LIMITs is incorrect; NEXT GROUP %d > LIMIT %d\n",fl->next_group_line,r->def_lines)); cob_set_exception (COB_EC_REPORT_PAGE_LIMIT); r->initiate_done = FALSE; return; } for(rf = fl->fields; rf; rf = rf->next) { if((rf->line && rf->line > r->def_lines)) { cob_runtime_error (_("INITIATE %s LINE %d exceeds PAGE LIMIT"),r->report_name,rf->line); DEBUG_LOG("rw",("PAGE LIMITs is incorrect; LINE %d > LIMIT %d\n",rf->line,r->def_lines)); cob_set_exception (COB_EC_REPORT_PAGE_LIMIT); r->initiate_done = FALSE; return; } if((rf->next_group_line && rf->next_group_line > r->def_lines)) { cob_runtime_error (_("INITIATE %s NEXT GROUP %d exceeds PAGE LIMIT"),r->report_name,rf->next_group_line); DEBUG_LOG("rw",("PAGE LIMITs is incorrect; NEXT GROUP %d > LIMIT %d\n",rf->next_group_line,r->def_lines)); cob_set_exception (COB_EC_REPORT_PAGE_LIMIT); r->initiate_done = FALSE; return; } } } /* * Verify that LINE # is within PAGE LIMITS */ static void limitCheckLine(cob_report *r, cob_report_line *fl) { limitCheckOneLine(r,fl); if(fl->child) limitCheckLine(r,fl->child); if(fl->sister) limitCheckLine(r,fl->sister); } /* * Verify that all LINE # are within PAGE LIMITS */ static void limitCheck(cob_report *r) { limitCheckLine(r,r->first_line); } static void saveLineCounter(cob_report *r) { int ln = r->curr_line; if(ln > r->def_lines) ln = 0; if(ln < 0) ln = 0; cob_set_int(r->page_counter,r->curr_page); cob_set_int(r->line_counter,ln); } /* * Search one LINE for Control field */ static void line_control_one (cob_report *r, cob_report_line *l, cob_field *f) { cob_report_field *rf; cob_report_control *rc; char fld[COB_MAX_WORDLEN + 1]; if (l == NULL) return; for(rf = l->fields; rf; rf = rf->next) { if(!(rf->flags & COB_REPORT_PRESENT)) continue; fld[0] = 0; for (rc = r->controls; rc; rc = rc->next) { if (rc->f == rf->control) { strncpy (fld, rc->name, COB_MAX_WORDLEN); fld[COB_MAX_WORDLEN] = 0; break; } } if(!(rf->flags & COB_REPORT_NEGATE) && !rf->present_now) { if(f == NULL) { /* New Page */ DEBUG_LOG("rw",("PRESENT NOW: %s NEW PAGE\n",fld)); if(rf->flags & COB_REPORT_PAGE) { /* PRESENT After New Page */ rf->present_now = 1; } } else if(rf->control == f) { /* Control field changed */ DEBUG_LOG("rw",("PRESENT NOW: %s control change\n",fld)); rf->present_now = 1; } } else if((rf->flags & COB_REPORT_NEGATE) && rf->present_now) { if(f == NULL) { /* New Page */ DEBUG_LOG("rw",("ABSENT NOW: %s NEW PAGE\n",fld)); if(rf->flags & COB_REPORT_PAGE) { /* PRESENT After New Page */ rf->present_now = 0; } } else if(rf->control == f) { /* Control field changed */ DEBUG_LOG("rw",("ABSENT NOW: %s control change\n",fld)); rf->present_now = 0; } } } } /* * Search Report for Control field */ static void line_control_chg(cob_report *r, cob_report_line *l, cob_field *f) { line_control_one(r,l,f); if(l->child) line_control_chg(r,l->child,f); if(l->sister) line_control_chg(r,l->sister,f); } /* * Write one line of report */ static void write_rec(cob_report *r, int opt) { cob_file *f = r->report_file; int num = opt & COB_WRITE_MASK; if (f->record->size > (unsigned int)r->def_cols) /* Truncate line if needed */ f->record->size = r->def_cols; if (r->code_is_present && r->code_len > 0) { /* Insert CODE IS value */ if (f->file) { if (num > 1 && (opt & COB_WRITE_LINES)) { opt = (opt & ~COB_WRITE_MASK) | 1; while (num > 0) { fwrite(r->code_is, r->code_len, 1, (FILE*)f->file); cob_write(f, f->record, opt, NULL, 0); memset(f->record->data,' ',f->record->size); num--; } } else { fwrite(r->code_is, r->code_len, 1, (FILE*)f->file); cob_write(f, f->record, opt, NULL, 0); } } } else { cob_write(f, f->record, opt, NULL, 0); } } /* * Write the Page Footing */ static void do_page_footing(cob_report *r) { cob_file *f = r->report_file; char *rec; if(r->in_page_footing) return; rec = (char *)f->record->data; r->in_page_footing = TRUE; report_line_type(r,r->first_line,COB_REPORT_PAGE_FOOTING); memset(rec,' ',f->record_max); if(r->curr_line < r->def_lines) { write_rec(r, COB_WRITE_BEFORE|COB_WRITE_LINES|(r->def_lines-r->curr_line)); r->curr_line = r->def_lines; r->incr_line = FALSE; } else { r->curr_line = 1; } saveLineCounter(r); r->first_detail = TRUE; r->in_page_footing = FALSE; } /* * Write the Page Heading */ static void do_page_heading(cob_report *r) { cob_file *f = r->report_file; char *rec; int opt; if(r->in_page_heading) return; opt = COB_WRITE_BEFORE | COB_WRITE_LINES | 1; rec = (char *)f->record->data; memset(rec,' ',f->record_max); if(!r->in_page_heading && !r->first_generate && r->def_lines > 0 && r->def_heading > 0 && r->curr_line <= r->def_lines && r->curr_line > r->def_heading) { /* Skip to end of page */ while(r->curr_line <= r->def_lines) { write_rec(r, opt); r->curr_line++; } if(r->curr_line > r->def_lines) /* Reset line to 1 */ r->curr_line = 1; saveLineCounter(r); } r->in_page_heading = TRUE; if(!r->first_generate) { r->curr_page++; } r->first_detail = FALSE; while(r->curr_line < r->def_heading) { /* Skip to Heading position on page */ write_rec(r, opt); r->curr_line++; saveLineCounter(r); } report_line_type(r,r->first_line,COB_REPORT_PAGE_HEADING); memset(rec,' ',f->record_max); while(r->curr_line < r->def_first_detail) { write_rec(r, opt); r->curr_line++; saveLineCounter(r); } clear_group_indicate(r->first_line); r->in_page_heading = FALSE; line_control_chg(r, r->first_line, NULL); } /* * Format one field into print line */ static void print_field(cob_report_field *rf, char *rec) { char wrk[COB_SMALL_BUFF]; size_t ln, k, i; size_t dest_pos = (size_t)rf->column - 1; cob_field_to_string(rf->f, wrk, sizeof(wrk)-1); wrk[COB_SMALL_MAX] = 0; /* keep analyzer happy */ ln = strlen(wrk); if(cobsetptr && !cobsetptr->cob_col_just_lrc) { /* Data justify is turned off, no adjustment */ } else if((rf->flags & COB_REPORT_COLUMN_RIGHT) && ln < rf->f->size) { dest_pos += rf->f->size - ln; } else if((rf->flags & COB_REPORT_COLUMN_CENTER)) { for(k=0; k < rf->f->size && wrk[0] == ' ' && ln > 0; k++) { /* remove leading spaces */ memmove(wrk,&wrk[1],ln); ln--; } i = 1- (ln & 1); if (ln < rf->f->size) { dest_pos += (rf->f->size - ln - i) / 2; } } else if((rf->flags & COB_REPORT_COLUMN_LEFT)) { for(k=0; k < rf->f->size && wrk[0] == ' ' && ln > 0; k++) { /* remove leading spaces */ memmove(wrk,&wrk[1],ln); ln--; } } memcpy (&rec[dest_pos], wrk, ln); } /* * GENERATE one report-line */ static void report_line(cob_report *r, cob_report_line *l) { cob_report_field *rf,*nrf,*prf; cob_file *f = r->report_file; char *rec,wrk[COB_SMALL_BUFF]; int bChkLinePlus = FALSE; int opt; opt = COB_WRITE_BEFORE | COB_WRITE_LINES | 1; rec = (char *)f->record->data; if(rec) { memset(rec,' ',f->record_max); memset(wrk,0,sizeof(wrk)); if(r->curr_line > r->def_last_detail && !r->in_report_footing && !r->in_page_footing) { /* Page overflow */ do_page_footing(r); do_page_heading(r); } if(!r->next_just_set && r->next_line_plus) { DEBUG_LOG("rw",(" Line# %d of Page# %d; ",r->curr_line,r->curr_page)); DEBUG_LOG("rw",("Execute NEXT GROUP PLUS %d\n",r->next_value)); opt = COB_WRITE_BEFORE | COB_WRITE_LINES | (r->next_value); write_rec(r, opt); r->curr_line += r->next_value; r->next_line_plus = FALSE; bChkLinePlus = TRUE; } else if(!r->next_just_set && r->next_line) { DEBUG_LOG("rw",(" Line# %d of Page# %d; ",r->curr_line,r->curr_page)); DEBUG_LOG("rw",("Execute NEXT GROUP LINE %d\n",r->next_value)); r->next_line = FALSE; if(r->curr_line > r->next_value) { do_page_footing(r); do_page_heading(r); } while(r->curr_line < r->next_value) { write_rec(r, opt); r->curr_line++; } bChkLinePlus = TRUE; } else if(!r->next_just_set && r->next_page) { DEBUG_LOG("rw",(" Line# %d of Page# %d; ",r->curr_line,r->curr_page)); DEBUG_LOG("rw",(" Execute NEXT GROUP PAGE\n")); r->next_page = FALSE; do_page_footing(r); do_page_heading(r); DEBUG_LOG("rw",(" Line# %d of Page# %d; after foot/head\n",r->curr_line,r->curr_page)); } else if( !(l->flags & COB_REPORT_LINE_PLUS) && (l->flags & COB_REPORT_LINE)) { if(r->curr_line > l->line) { DEBUG_LOG("rw",(" Eject Page %d from line %d for Line %d\n",r->curr_page,r->curr_line,l->line)); do_page_footing(r); if(r->in_report_footing) { r->curr_page++; /* Now on next page */ r->curr_line = 1; } else { do_page_heading(r); } r->first_detail = FALSE; } while(r->curr_line < l->line) { write_rec(r, opt); r->curr_line++; } } else { bChkLinePlus = TRUE; } if(bChkLinePlus && (l->flags & COB_REPORT_LINE_PLUS) && l->line > 1) { if(r->curr_line != r->def_first_detail || r->def_first_detail == 0) { opt = COB_WRITE_BEFORE | COB_WRITE_LINES | (l->line - 1); write_rec(r, opt); r->curr_line += l->line - 1; } } bChkLinePlus = FALSE; if(r->curr_line > r->def_last_detail && !r->in_report_footing && !r->in_page_heading && !r->in_page_footing) { /* Page overflow */ do_page_footing(r); do_page_heading(r); } saveLineCounter(r); if(l->fields == NULL) { set_next_info(r,l); return; } if(l->suppress) { #ifdef COB_DEBUG_LOG if(DEBUG_ISON("rw")) { reportDumpOneLine(r,l,0,1); DEBUG_LOG("rw",(" ^^^ Complete line Suppressed ^^^\n\n")); } #endif set_next_info(r,l); return; } /* * Copy fields to print line area */ for(rf = l->fields; rf; rf = rf->next) { if((rf->flags & COB_REPORT_GROUP_ITEM)) { if(rf->suppress) { /* group item SUPPRESSed printing, so skip to next field */ rf->suppress = FALSE; prf = rf; for(nrf = rf->next; nrf && nrf->level > rf->level; nrf = nrf->next) { prf = nrf; } if(prf) { rf = prf; /* Continue from here */ continue; } break; /* No more so, end of print line */ } continue; /* Group items are not printed */ } if( (rf->flags & COB_REPORT_PRESENT) && !rf->present_now) { continue; } if(rf->suppress || rf->group_indicate) { if(rf->source) { /* Copy source field in */ cob_field_to_string(rf->source, wrk, sizeof(wrk)-1); } continue; } if(rf->source) { /* Copy source field in */ cob_move(rf->source,rf->f); print_field(rf, rec); } else if(rf->litval) { /* Refresh literal value */ if(rf->f) { cob_str_move(rf->f, (unsigned char*)rf->litval, rf->litlen); } memcpy(&rec[rf->column-1], rf->litval, rf->litlen); } else if(rf->f) { print_field(rf, rec); } if((rf->flags & COB_REPORT_GROUP_INDICATE)) { /* Suppress subsequent printings */ rf->group_indicate = TRUE; } } } #ifdef COB_DEBUG_LOG if(DEBUG_ISON("rw")) { reportDumpOneLine(r,l,0,1); for(opt = f->record_max; opt > 1 && rec[opt-1] == ' '; opt--); DEBUG_LOG("rw",("%.*s\n\n",opt,rec)); } #endif for(rf = l->fields; rf; rf = rf->next) { rf->present_now = (rf->flags & COB_REPORT_NEGATE)?1:0; } if(rec) { opt = COB_WRITE_BEFORE | COB_WRITE_LINES | 1; write_rec(r, opt); r->curr_line ++; saveLineCounter(r); } set_next_info(r,l); } /* * GENERATE one report-line */ static void report_line_and(cob_report *r, cob_report_line *l, int type) { if(l == NULL) return; if(l->fields == NULL && l->child != NULL) { if(l->flags & type) { report_line(r,l); if(l->child) { report_line_type(r,l->child,COB_REPORT_LINE); } return; } l = l->child; } report_line_type(r,l,type); } /* * Find Report Line of given type */ static cob_report_line * get_line_type(cob_report *r, cob_report_line *l, int type) { cob_report_line *t; if(l == NULL) return NULL; if(l->flags & type) { return l; } if(l->child) if ((t = get_line_type(r,l->child,type)) != NULL) return t; if(l->sister) return get_line_type(r,l->sister,type); return NULL; } /* * GENERATE report-line(s) of type */ static int report_line_type(cob_report *r, cob_report_line *l, int type) { int curseq,sisseq; if(l == NULL) return 0; if(l->flags & type) { report_line(r,l); if(l->child) { report_line_type(r,l->child,COB_REPORT_LINE); } if(l->sister) { if((type == COB_REPORT_CONTROL_FOOTING) && (l->sister->flags & COB_REPORT_CONTROL_FOOTING)) { curseq = get_control_sequence(r,l); sisseq = get_control_sequence(r,l->sister); if(curseq > 0 && sisseq > 0 && sisseq > curseq) { #ifdef COB_DEBUG_LOG reportDumpOneLine(r,l->sister,0,1); #endif return 1; } } report_line_type(r,l->sister,type); } return 1; } if(l->child) if(report_line_type(r,l->child,type)) return 1; if(l->sister) return report_line_type(r,l->sister,type); return 0; } /* * SUM all DETAIL counters */ static void sum_all_detail(cob_report *r) { cob_report_sum_ctr *sc; cob_report_sum *rs; int bHasSum = FALSE; /* * Add up all SUM counter values */ for(sc = r->sum_counters; sc; sc = sc->next) { for(rs = sc->sum; rs && !sc->subtotal; rs = rs->next) { if(!bHasSum) { bHasSum = TRUE; DEBUG_LOG("rw",(" Do SUM detail counters:\n")); } DEBUG_LOG("rw",(" .. %-20s ",sc->name)); cob_add_fields(sc->counter,rs->f,sc->counter); } } } /* * If the counter is part of another SUM then it is 'rolling forward' */ static void sum_this_counter(cob_report *r, cob_field *counter) { cob_report_sum_ctr *sc; cob_report_sum *rs; for(sc = r->sum_counters; sc; sc = sc->next) { for(rs = sc->sum; rs; rs = rs->next) { if(rs->f == counter) { DEBUG_LOG("rw",("SUM %s forward ",sc->name)); for(rs = sc->sum; rs; rs = rs->next) { cob_add_fields(sc->counter,rs->f,sc->counter); } break; } } } } /* * ZERO counters for a given control level */ static void zero_all_counters(cob_report *r, int flag, cob_report_line *l) { cob_report_sum_ctr *sc; cob_report_sum *rs; cob_report_control *rc; cob_report_control_ref *rr; l = get_print_line(l); /* * ZERO SUM counter */ for(sc = r->sum_counters; sc; sc = sc->next) { for(rs = sc->sum; rs; rs = rs->next) { if((flag & COB_REPORT_CONTROL_FOOTING_FINAL)) { if(sc->control_final) { DEBUG_LOG("rw",("ZERO SUM Counter %s for FOOTING FINAL\n",sc->name)); cob_field_init(sc->counter); } } else if(sc->control) { rc = sc->control; for(rr = rc->control_ref; rr; rr=rr->next) { if(rr->ref_line && (rr->ref_line->flags & COB_REPORT_CONTROL_HEADING)) continue; if(rr->ref_line && (rr->ref_line->flags & COB_REPORT_CONTROL_HEADING_FINAL)) continue; if(l != NULL && l != get_print_line(rr->ref_line)) continue; if(rr->ref_line && (rr->ref_line->flags & flag)) { sum_this_counter(r,sc->counter); #if defined(COB_DEBUG_LOG) DEBUG_LOG("rw",("ZERO SUM counter %s for ",sc->name)); dumpFlags(rr->ref_line->flags,0,(char*)rc->name); DEBUG_LOG("rw",("\n")); #endif cob_field_init(sc->counter); } } } } } } /* * Runtime starting up */ void cob_init_reportio(cob_global *gptr, cob_settings *sptr) { int k; cobglobptr = gptr; cobsetptr = sptr; for(k=0; k < MAX_ACTIVE_REPORTS; k++) active_reports[k] = NULL; } /* * Runtime exiting */ void cob_exit_reportio() { int k; for(k=0; k < MAX_ACTIVE_REPORTS; k++) { if(active_reports[k] != NULL) { free_control_fields (active_reports[k]); } } } /* * INITIATE report */ void cob_report_initiate(cob_report *r) { cob_report_control *rc; cob_report_control_ref *rr; cob_report_sum_ctr *sc; int k; reportInitialize(); if(r->initiate_done) { cob_runtime_error (_("INITIATE %s was already done"),r->report_name); DEBUG_LOG("rw",("REPORT was already INITIATEd\n")); cob_set_exception (COB_EC_REPORT_ACTIVE); return; } if (r->def_lines > 9999) r->def_lines = 9999; if (r->def_cols > 999 || r->def_cols < 1) r->def_cols = 999; if((r->def_first_detail > 0 && !(r->def_first_detail >= r->def_heading)) || (r->def_last_detail > 0 && !(r->def_last_detail >= r->def_first_detail)) || (r->def_footing > 0 && !(r->def_footing >= r->def_heading)) || (r->def_footing > 0 && !(r->def_footing >= r->def_last_detail)) || (r->def_lines > 0 && !(r->def_lines >= r->def_heading)) || (r->def_lines > 0 && !(r->def_lines >= r->def_footing))) { cob_runtime_error (_("INITIATE %s PAGE LIMIT problem"),r->report_name); #if defined(COB_DEBUG_LOG) DEBUG_LOG("rw",("PAGE LIMITs is incorrect\n")); reportDump(r,"INITIATE"); #endif cob_set_exception (COB_EC_REPORT_PAGE_LIMIT); return; } r->curr_page = 1; r->curr_line = 0; r->incr_line = TRUE; saveLineCounter(r); #if defined(COB_DEBUG_LOG) reportDump(r,"INITIATE"); #endif r->initiate_done = TRUE; limitCheck(r); if(!r->initiate_done) /* Problem during LIMIT check */ return; r->first_detail = TRUE; r->first_generate = TRUE; r->next_value = 0; r->next_line = 0; r->next_line_plus = FALSE; r->next_page = FALSE; /* * Allocate temp area for each control field */ for(rc = r->controls; rc; rc = rc->next) { if(rc->val) { cob_field_free(rc->val); rc->val = NULL; } if(rc->sf) { cob_field_free(rc->sf); rc->sf = NULL; } rc->val = cob_field_dup(rc->f,0); rc->sf = cob_field_dup(rc->f,0); for(k=0; k < MAX_ACTIVE_REPORTS; k++) { if (active_reports[k] == r) break; if (active_reports[k] == NULL) { active_reports[k] = r; break; } } rc->has_heading = FALSE; rc->has_footing = FALSE; for(rr = rc->control_ref; rr; rr = rr->next) { if(rr->ref_line->flags & COB_REPORT_CONTROL_HEADING) rc->has_heading = TRUE; if(rr->ref_line->flags & COB_REPORT_CONTROL_HEADING_FINAL) rc->has_heading = TRUE; if(rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING) rc->has_footing = TRUE; if(rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING_FINAL) rc->has_footing = TRUE; } } for(sc = r->sum_counters; sc; sc = sc->next) { cob_field_init(sc->counter); } } /* * TERMINATE report */ int cob_report_terminate (cob_report *r, int ctl) { cob_report_control *rc; cob_report_control_ref *rr; cob_report_line *pl; if (!r->initiate_done) { DEBUG_LOG("rw",("INITIATE was never done!\n")); cob_runtime_error (_("TERMINATE %s but no INITIATE was done"),r->report_name); cob_set_exception (COB_EC_REPORT_INACTIVE); #if 0 /* TODO: if not enabled: ignore, if enabled and PROPAGATE ON (or TRY) active: handle */ return 0; #else cob_stop_run (1); #endif } if (r->first_generate) { DEBUG_LOG("rw",("No GENERATE was ever done!\n")); return 0; } if (ctl > 0) { /* Continue Processing Footings from last point */ for (rc = r->controls; rc; rc = rc->next) { for (rr = rc->control_ref; rr; rr = rr->next) { if (rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING) { pl = get_print_line(rr->ref_line); if (rr->ref_line->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintFooting; /* Continue Footings */ } if (pl != rr->ref_line && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintFooting; /* Continue Footings */ } } if (rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING_FINAL) { pl = get_print_line(rr->ref_line); if (rr->ref_line->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintFootingFinal; /* Continue Footings */ } if (pl != rr->ref_line && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintFootingFinal; /* Continue Footings */ } } if (rr->ref_line->flags & COB_REPORT_FOOTING) { pl = get_print_line(rr->ref_line); if (rr->ref_line->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintReportFooting;/* Continue Footings */ } if (pl != rr->ref_line && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintReportFooting;/* Continue Footings */ } } } } DEBUG_LOG("rw",("Could not find Declarative %d\n",ctl)); pl = get_line_type(r, r->first_line,COB_REPORT_CONTROL_FOOTING_FINAL); if( pl && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Final Declaratives %d\n",ctl)); goto PrintFootingFinal; /* Continue Footings */ } pl = get_line_type(r, r->first_line,COB_REPORT_FOOTING); if (pl && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Report Declaratives %d\n",ctl)); goto PrintReportFooting; /* Continue Footings */ } } else { reportInitialize(); #if defined(COB_DEBUG_LOG) reportDump(r,"TERMINATE"); #endif /* Do CONTROL FOOTING breaks */ for(rc = r->controls; rc; rc = rc->next) { for(rr = rc->control_ref; rr; rr = rr->next) { if(rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING) { if(rr->ref_line->use_decl) { DEBUG_LOG("rw",(" Return for %s Footing Declaratives %d\n", rc->name,rr->ref_line->use_decl)); return rr->ref_line->use_decl; } pl = get_print_line(rr->ref_line); if(pl != rr->ref_line && pl->use_decl) { DEBUG_LOG("rw",(" Return for %s Footing Declaratives %d.\n", rc->name,pl->use_decl)); return pl->use_decl; /* Back for DECLARATIVES */ } PrintFooting: if(!rc->suppress) report_line_and(r,rr->ref_line,COB_REPORT_CONTROL_FOOTING); rc->suppress = FALSE; zero_all_counters(r, COB_REPORT_CONTROL_FOOTING,pl); } } } } /* Do CONTROL FOOTING FINAL */ pl = get_line_type(r, r->first_line,COB_REPORT_CONTROL_FOOTING_FINAL); if(pl) { if(pl->use_decl) { DEBUG_LOG("rw",(" Return for Footing Final Declaratives %d.\n", pl->use_decl)); return pl->use_decl; /* Back for DECLARATIVES */ } PrintFootingFinal: report_line_type(r,r->first_line,COB_REPORT_CONTROL_FOOTING_FINAL); } zero_all_counters(r, COB_REPORT_CONTROL_FOOTING_FINAL,NULL); do_page_footing(r); pl = get_line_type(r, r->first_line,COB_REPORT_FOOTING); if(pl) { if(pl->use_decl) { DEBUG_LOG("rw",(" Return for Report Footing Declaratives %d.\n", pl->use_decl)); return pl->use_decl; /* Back for DECLARATIVES */ } PrintReportFooting: r->in_report_footing = TRUE; report_line_type(r,r->first_line,COB_REPORT_FOOTING); r->in_report_footing = FALSE; } free_control_fields (r); r->initiate_done = FALSE; return 0; } /* * GENERATE report-line */ int cob_report_generate (cob_report *r, cob_report_line *l, int ctl) { cob_report_control *rc, *rp; cob_report_control_ref *rr; cob_report_line *pl; int maxctl,ln,num,gengrp; #if defined(COB_DEBUG_LOG) char wrk[256]; #endif reportInitialize(); if (!r->initiate_done) { cob_runtime_error (_("GENERATE %s but no INITIATE was done"),r->report_name); cob_set_exception (COB_EC_REPORT_INACTIVE); #if 0 /* TODO: if not enabled: ignore, if enabled and PROPAGATE ON (or TRY) active: handle */ return 0; #else cob_stop_run (1); #endif } r->foot_next_page = FALSE; DEBUG_LOG("rw",("~ Enter %sGENERATE with ctl == %d\n",r->first_generate?"first ":"",ctl)); if (ctl > 0) { /* Continue Processing Footings from last point */ for (rc = r->controls; rc; rc = rc->next) { for (rr = rc->control_ref; rr; rr = rr->next) { if (rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING) { pl = get_print_line(rr->ref_line); if (rr->ref_line->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintFooting; /* Continue Footings */ } if (pl != rr->ref_line && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); goto PrintFooting; /* Continue Footings */ } } if (rr->ref_line->flags & COB_REPORT_CONTROL_HEADING) { pl = get_print_line(rr->ref_line); if (rr->ref_line->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); if(r->first_generate) goto PrintFirstHeading; goto PrintHeading; /* Continue Footings */ } if (pl != rr->ref_line && pl->use_decl == ctl) { DEBUG_LOG("rw",(" Continue after Declaratives %d\n",ctl)); if (r->first_generate) { goto PrintFirstHeading; } goto PrintHeading; /* Continue Headings */ } } } } DEBUG_LOG("rw",("Could not find Declarative %d\n",ctl)); } if (r->incr_line) { r->incr_line = FALSE; r->curr_line++; saveLineCounter(r); } if (r->first_generate) { /* * First GENERATE of the report */ DEBUG_LOG("rw",("Process First GENERATE\n")); report_line_type(r,r->first_line,COB_REPORT_HEADING); do_page_heading(r); /* do CONTROL Headings */ for(rc = r->controls; rc; rc = rc->next) { for(rr = rc->control_ref; rr; rr = rr->next) { if(rr->ref_line->flags & COB_REPORT_CONTROL_HEADING) { if(rr->ref_line->use_decl) { DEBUG_LOG("rw",(" Return first %s Heading Declaratives %d\n", rc->name,rr->ref_line->use_decl)); return rr->ref_line->use_decl; } pl = get_print_line(rr->ref_line); if(pl != rr->ref_line && pl->use_decl) { DEBUG_LOG("rw",(" Return first %s Heading Declaratives %d.\n", rc->name,pl->use_decl)); return pl->use_decl; /* Back for DECLARATIVES */ } PrintFirstHeading: report_line_and(r,rr->ref_line,COB_REPORT_CONTROL_HEADING); } } cob_move (rc->f,rc->val); /* Save current field data */ rc->data_change = FALSE; } DEBUG_LOG("rw",("Finished First GENERATE\n")); } else { if(r->curr_line > r->def_last_detail) { /* Page overflow */ do_page_footing(r); r->curr_line = 1; do_page_heading(r); r->first_detail = FALSE; } else if(r->curr_line <= 1 || r->first_detail) { if(r->first_detail) { r->curr_line = 1; } do_page_heading(r); r->first_detail = FALSE; } /* * Check for FOOTINGs on other GENERATEs */ maxctl = 0; for(rc = r->controls; rc; rc = rc->next) { rc->data_change = (cob_cmp(rc->f,rc->val) != 0); if(rc->data_change) { /* Data change, implies control break at lower levels */ #if defined(COB_DEBUG_LOG) DEBUG_LOG("rw",(" Control Break %s order %d changed from ", rc->name,rc->sequence)); cob_field_to_string(rc->val, wrk, sizeof(wrk)-1); DEBUG_LOG("rw",("'%s' to ",wrk)); cob_field_to_string(rc->f, wrk, sizeof(wrk)-1); DEBUG_LOG("rw",("'%s'\n",wrk)); #endif cob_move(rc->f, rc->sf); /* Save new CONTROL value */ cob_move(rc->val,rc->f); /* Prev value for FOOTING */ if(rc->sequence > maxctl) maxctl = rc->sequence; } } if(maxctl > 0) { for(rp = r->controls; rp; rp = rp->next) { if(rp->sequence < maxctl && !rp->data_change) { rp->data_change = TRUE; DEBUG_LOG("rw",(" Control Break %s order %d also ...\n", rp->name,rp->sequence)); cob_move(rp->f, rp->sf); /* Save CONTROL value */ cob_move(rp->val,rp->f); /* Prev value for FOOTING */ } } } for(rc = r->controls; rc; rc = rc->next) { if(rc->data_change) { /* Data change, Check for PRESENT WHEN control-id */ line_control_chg(r, r->first_line, rc->f); } } for(rc = r->controls; rc; rc = rc->next) { if(rc->data_change) { for(rr = rc->control_ref; rr; rr = rr->next) { if(rr->ref_line->flags & COB_REPORT_CONTROL_FOOTING) { if(rr->ref_line->use_decl) { DEBUG_LOG("rw",(" Return for %s Footing Declaratives %d\n", rc->name,rr->ref_line->use_decl)); return rr->ref_line->use_decl; } pl = get_print_line(rr->ref_line); if(pl != rr->ref_line && pl->use_decl) { DEBUG_LOG("rw",(" Return for %s Footing Declaratives %d.\n", rc->name,pl->use_decl)); return pl->use_decl; /* Back for DECLARATIVES */ } PrintFooting: if(!rc->suppress && !rr->ref_line->suppress) report_line_and(r,rr->ref_line,COB_REPORT_CONTROL_FOOTING); rc->suppress = FALSE; rr->ref_line->suppress = FALSE; zero_all_counters(r, COB_REPORT_CONTROL_FOOTING,pl); clear_group_indicate(r->first_line); r->next_just_set = FALSE; if(r->next_page) { r->foot_next_page = TRUE; r->next_page = FALSE; } } } cob_move(rc->sf,rc->f); /* Put new CONTROL value back */ } } if(r->foot_next_page) { DEBUG_LOG("rw",(" Line# %d of Page# %d; ",r->curr_line,r->curr_page)); DEBUG_LOG("rw",(" Execute NEXT GROUP PAGE after footings\n")); r->next_page = FALSE; r->foot_next_page = FALSE; do_page_footing(r); do_page_heading(r); } /* * Check for Control Headings */ for(rc = r->controls; rc; rc = rc->next) { if(rc->data_change) { for(rr = rc->control_ref; rr; rr = rr->next) { if(rr->ref_line->flags & COB_REPORT_CONTROL_HEADING) { if(rr->ref_line->use_decl) { DEBUG_LOG("rw",(" Return for %s Heading Declaratives %d\n", rc->name,rr->ref_line->use_decl)); return rr->ref_line->use_decl; } pl = get_print_line(rr->ref_line); if(pl != rr->ref_line && pl->use_decl) { DEBUG_LOG("rw",(" Return for %s Heading Declaratives %d.\n", rc->name,pl->use_decl)); return pl->use_decl; /* Back for DECLARATIVES */ } PrintHeading: if(!rr->ref_line->suppress) report_line_and(r,rr->ref_line,COB_REPORT_CONTROL_HEADING); rr->ref_line->suppress = FALSE; } } cob_move (rc->f,rc->val); /* Save current field data */ } rc->data_change = FALSE; } } sum_all_detail(r); /* SUM detail counters */ if(l == NULL) { /* GENERATE */ } else if(l->suppress) { l->suppress = FALSE; } else { gengrp = 0; if(l->fields == NULL && l->child != NULL && l->child->sister != NULL) { l = l->child; /* Multiple Detail Lines in group */ gengrp = 1; } num = ln = 0; for(pl = l; pl; pl = pl->sister) { if( NOTDETAIL(pl->flags) ) break; if((pl->flags & COB_REPORT_LINE_PLUS) && pl->line > 1) { ln += pl->line; } num++; if(!gengrp) break; } if(num > 1 && (r->curr_line + ln) > r->def_last_detail) { /* Page overflow */ do_page_footing(r); r->curr_line = 1; do_page_heading(r); r->first_detail = FALSE; saveLineCounter(r); } for(pl = l; pl; pl = pl->sister) { if( NOTDETAIL(pl->flags) ) break; l = get_print_line(pl); /* Find line with data fields */ if(!l->suppress) { r->next_just_set = FALSE; report_line(r,l); /* Generate this DETAIL line */ } l->suppress = FALSE; if(!gengrp) break; } } /* * Zero out SUM counters */ zero_all_counters(r, COB_REPORT_DETAIL, NULL); clear_suppress(r->first_line); r->first_generate = FALSE; r->next_just_set = FALSE; r->curr_line--; r->incr_line = TRUE; saveLineCounter(r); return 0; } /* * SUPPRESS printing of this CONTROL level */ void cob_report_suppress(cob_report *r, cob_report_line *l) { cob_report_control *rc; cob_report_control_ref *rr; cob_report_line *pl; for(rc = r->controls; rc; rc = rc->next) { for(rr = rc->control_ref; rr; rr = rr->next) { if(rr->ref_line == l) { rc->suppress = TRUE; return; } pl = get_print_line(rr->ref_line); if(pl == l) { rc->suppress = TRUE; return; } } } cob_runtime_error (_("could not find line to SUPPRESS in report %s"),r->report_name); }