static void gml_ixxx_common( const gmltag * entry, int hx_lvl ) { bool idseen; bool refidseen; bool seeseen; bool seeidseen; bool pgseen; bool printseen; char * p; ereftyp pgvalue; char * pgtext; size_t pgtextlen; size_t printtxtlen; size_t seetextlen; char * printtxt; char * seetext; ref_entry * refwork; ref_entry reid; ref_entry * rewk; ref_entry refid; ref_entry * refwk; ref_entry reseeid; ref_entry * rswk; ix_h_blk * ihm1; ix_e_blk * ixewk; ix_e_blk * ixewksav; ix_h_blk * ixhwk; ix_h_blk * * ixhwork; uint32_t wkpage; size_t txtlen; char * txt; char hxstring[TAG_NAME_LENGTH +1]; char lvlc; if( !GlobalFlags.index ) { // index option not active scan_start = scan_stop + 1; // ignore tag return; } lvlc = '0' + (char)hx_lvl; *hxstring = GML_char; // construct tagname for possible error msg strcpy_s( (hxstring + 1), TAG_NAME_LENGTH, entry->tagname ); if( (hxstring[2] == lvlc) && // :Ix tags not allowed before :GDOC !((ProcFlags.doc_sect >= doc_sect_gdoc) || (ProcFlags.doc_sect_nxt >= doc_sect_gdoc)) ) { g_err( err_tag_before_gdoc, hxstring ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } if( hx_lvl > 1 ) { // test for missing previous parent index tag if( ixhtag[hx_lvl - 1] == NULL ) { g_err( err_parent_undef ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } idseen = false; pgseen = false; refidseen = false; printseen = false; seeseen = false; seeidseen = false; ixewk = NULL; pgvalue = pgnone; pgtext = NULL; pgtextlen = 0; printtxt = NULL; printtxtlen = 0; seetext = NULL; wkpage = page + 1; p = scan_start; ProcFlags.tag_end_found = false; /***********************************************************************/ /* Scan attributes for :Ix :IHx :IREF */ /* */ /* id= */ /* refid= */ /* pg= */ /* print= */ /* see= */ /* seeid= */ /***********************************************************************/ for( ;; ) { if( ProcFlags.tag_end_found ) { break; } while( is_space_tab_char( *p ) ) { p++; } if( *p == '.' ) { ProcFlags.tag_end_found = true; break; } if( *p == '\0' ) { break; } /*******************************************************************/ /* ID='xxxxxxxx' for :Ix :IHx */ /*******************************************************************/ if( !strnicmp( "id", p, 2 ) ) { p += 2; p = get_refid_value( p ); if( (val_start != NULL) && (val_len > 0) ) { if( hx_lvl > 0 ) { // :Ix :IHx idseen = true; // id attribute found init_ref_entry( &reid, val_start, val_len ); rewk = find_refid( iref_dict, reid.id ); if( rewk != NULL ) { if( rewk->lineno != reid.lineno ) { g_err( inf_id_duplicate ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } } else { // not allowed for :IREF g_err( err_refid_not_allowed, hxstring ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } scan_start = p; continue; } /*******************************************************************/ /* REFID='xxxxxxxx' for :IREF :I2 :I3 */ /*******************************************************************/ if( !strnicmp( "refid", p, 5 ) ) { p += 5; p = get_refid_value( p ); if( val_start != NULL && val_len > 0 ) { if( (hx_lvl == 0) || ((hx_lvl > 1) && (hxstring[2] == lvlc)) ) { fill_id( &refid, val_start, val_len ); refidseen = true; // refid attribute found refwk = find_refid( iref_dict, refid.id ); if( refwk == NULL ) { // refid not in dict if( GlobalFlags.lastpass ) {// this is an error g_err( inf_id_unknown );// during lastpass err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } } else { // not allowed for :I1 and :IHx g_err( err_refid_not_allowed, hxstring ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } scan_start = p; continue; } /*******************************************************************/ /* PG= for :IREF :Ix */ /*******************************************************************/ if( !strnicmp( "pg", p, 2 ) ) { p += 2; p = get_att_value( p ); scan_start = p; if( val_start == NULL || val_len == 0 ) { // no valid pg continue; // ignore } if( quote_char == '\0' ) { // value not quoted if( !strnicmp( "start", val_start, 5 ) ) { pgvalue = pgstart; } else if( !strnicmp( "end", val_start, 3 ) ) { pgvalue = pgend; } else if( !strnicmp( "major", val_start, 5 ) ) { pgvalue = pgmajor; } else { continue; // ignore } } else { pgvalue = pgstring; pgtext = mem_alloc( val_len + 1 ); strncpy( pgtext, val_start, val_len );// use text instead of pageno *(pgtext + val_len) = '\0'; pgtextlen = val_len; } pgseen = true; continue; } /*******************************************************************/ /* PRINT= for :IHx */ /*******************************************************************/ if( !strnicmp( "print", p, 5 ) ) { p += 5; p = get_att_value( p ); scan_start = p; if( val_start == NULL || val_len == 0 ) { continue; // ignore } printtxt = mem_alloc( val_len + 1 ); printtxtlen = val_len; strncpy( printtxt, val_start, val_len ); *(printtxt + val_len) = '\0'; printseen = true; continue; } /*******************************************************************/ /* SEE='xxxxxxxx' for :IREF :IH1 :IH2 */ /*******************************************************************/ if( !strnicmp( "see", p, 3 ) ) { p += 3; p = get_att_value( p ); scan_start = p; if( (val_start != NULL) || val_len > 0 ) { if( hx_lvl == 0 || ((hx_lvl < 3) && (hxstring[3] == lvlc)) ) {// :IREF :IH1 :IH2 seetext = mem_alloc( val_len +1 ); strncpy( seetext, val_start, val_len ); *(seetext + val_len) = '\0'; seetextlen = val_len; seeseen = true; } else { // not allowed for :IH3, :Ix g_err( err_refid_not_allowed, hxstring ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } continue; } /*******************************************************************/ /* SEEID='xxxxxxxx' for :IREF :IH1 :IH2 */ /*******************************************************************/ if( !strnicmp( "seeid", p, 5 ) ) { p += 5; p = get_refid_value( p ); if( (val_start != NULL) && (val_len > 0) ) { if( (hx_lvl <= 3) && (hxstring[3] == lvlc) ) { seeidseen = true; fill_id( &reseeid, val_start, val_len );// copy lower id rswk = find_refid( iref_dict, reseeid.id ); if( rswk == NULL ) {// not in dict, this is an error if( GlobalFlags.lastpass ) { // during lastpass g_err( inf_id_unknown ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } } else { // not allowed for :IH3, :Ix :IREF g_err( err_refid_not_allowed, hxstring ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } } scan_start = p; continue; } /*******************************************************************/ /* no more valid attributes */ /*******************************************************************/ break; } if( ProcFlags.tag_end_found ) { // tag end ? p++; if( hx_lvl > 0 ) { // we need a text line for :Ix :IHx if( !*p ) { get_line( true ); p = buff2; } } } /***********************************************************************/ /* process the found attributes and the text line */ /***********************************************************************/ txt = p; txtlen = strlen( p ); if( !pgseen ) { pgvalue = pgpageno; // set default } if( hx_lvl == 0 ) { // :IREF tag /***********************************************************************/ /* processing for :IREF */ /***********************************************************************/ if( !refidseen ) { // refid= missing g_err( err_att_missing ); err_count++; file_mac_info(); scan_start = scan_stop + 1; return; } if( GlobalFlags.lastpass ) { if( refidseen && (refwk != NULL) ) { ixhwk = refwk->u.refb.hblk; } else { ixhwk = ixhtag[hx_lvl]; } /***************************************************************/ /* create index entry with page no / text */ /***************************************************************/ if( ixhwk->entry == NULL ) { // first entry ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, pgtext, pgtextlen ); } else { if( pgvalue == pgmajor ) { // major becomes first in chain ixewksav = ixhwk->entry; ixhwk->entry = NULL; ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, pgtext, pgtextlen ); ixewk->next = ixewksav; } else { ixewk = ixhwk->entry; if( pgvalue < pgstring ) { // pageno variants if( ixewk->entry_typ < pgstring ) { while( ixewk->next != NULL ) {// insert before pgstring if( ixewk->next->entry_typ >= pgstring ) { break; } ixewk = ixewk->next; } } else { ixewksav = ixhwk->entry; ixhwk->entry = NULL; ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, pgtext, pgtextlen ); ixewk->next = ixewksav; } if( ixewk->u.page_no != wkpage ) { ixewksav = ixewk->next; ixewk->next = NULL; ixewk = fill_ix_e_blk( &(ixewk->next), ixhwk, pgvalue, pgtext, pgtextlen ); ixewk->next = ixewksav; } } else { while( ixewk->next != NULL ) { // find last entry ixewk = ixewk->next; } ixewk = fill_ix_e_blk( &(ixewk->next), ixhwk, pgvalue, pgtext, pgtextlen ); } } } } } else // :Ix :IHx tags if( ((hxstring[2] == lvlc) ) ) { // test for :Ix /***********************************************************************/ /* processing for :Ix */ /***********************************************************************/ switch( hx_lvl ) { // processing for :I1 :I2 :I3 case 1 : ixhwork = &index_dict; ixhwk = find_create_ix_h_entry( ixhwork, &printtxt, printtxtlen, txt, txtlen, hx_lvl ); printtxt = NULL; ixhtag[hx_lvl] = ixhwk; break; case 2 : case 3 : ihm1 = ixhtag[hx_lvl - 1]; if( refidseen && (refwk != NULL) ) { if( hx_lvl > refwk->u.refb.hblk->ix_lvl ) { ixhwork = &(refwk->u.refb.hblk->lower); } else { ixhwork = &(refwk->u.refb.hblk); } } else { ixhwork = &(ixhtag[hx_lvl - 1]->lower); } ixhwk = find_create_ix_h_entry( ixhwork, &printtxt, printtxtlen, txt, txtlen, hx_lvl ); printtxt = NULL; if( !refidseen ) { ixhtag[hx_lvl] = ixhwk; } break; default: break; } /*******************************************************************/ /* create index entry with page no / text */ /*******************************************************************/ if( ixhwk->entry == NULL ) { // first entry ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, pgtext, pgtextlen ); } else { if( pgvalue == pgmajor ) { // major becomes first in chain ixewksav = ixhwk->entry; ixhwk->entry = NULL; ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, pgtext, pgtextlen ); ixewk->next = ixewksav; } else { ixewk = ixhwk->entry; if( pgvalue < pgstring ) { // pageno variants if( ixewk->entry_typ < pgstring ) { while( ixewk->next != NULL ) {// insert before pgstring if( ixewk->next->entry_typ >= pgstring ) { break; } ixewk = ixewk->next; } } else { ixewksav = ixhwk->entry; ixhwk->entry = NULL; ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, pgtext, pgtextlen ); ixewk->next = ixewksav; } if( ixewk->u.page_no != wkpage ) { ixewksav = ixewk->next; ixewk->next = NULL; ixewk = fill_ix_e_blk( &(ixewk->next), ixhwk, pgvalue, pgtext, pgtextlen ); ixewk->next = ixewksav; } } else { while( ixewk->next != NULL ) { // find last entry ixewk = ixewk->next; } ixewk = fill_ix_e_blk( &(ixewk->next), ixhwk, pgvalue, pgtext, pgtextlen ); } } } } else // :IHx if( ((hxstring[3] == lvlc) ) ) { // test for :IHx /***********************************************************************/ /* processing for :IHx */ /***********************************************************************/ switch( hx_lvl ) { // processing for :IH1 :IH2 :IH3 case 1 : ixhwork = &index_dict; ixhwk = find_create_ix_h_entry( ixhwork, &printtxt, printtxtlen, txt, txtlen, hx_lvl ); printtxt = NULL; ixhtag[hx_lvl] = ixhwk; break; case 2 : case 3 : ihm1 = ixhtag[hx_lvl - 1]; ixhwork = &(ixhtag[hx_lvl - 1]->lower); ixhwk = find_create_ix_h_entry( ixhwork, &printtxt, printtxtlen, txt, txtlen, hx_lvl ); printtxt = NULL; ixhtag[hx_lvl] = ixhwk; break; default: break; } if( seeseen ) { pgvalue = pgsee; if( ixhwk->entry == NULL ) { ixewk = fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgvalue, seetext, seetextlen ); } else { ixewk = ixhwk->entry; while( ixewk->next != NULL ) { // find last entry ixewk = ixewk->next; } ixewk = fill_ix_e_blk( &(ixewk->next), ixhwk, pgvalue, seetext, seetextlen ); } } else { if( seeidseen ) { ix_e_blk * * anchor; pgvalue = pgsee; if( ixhwk->entry == NULL ) { anchor = &(ixhwk->entry); } else { ixewk = ixhwk->entry; while( ixewk->next != NULL ) { // find last entry ixewk = ixewk->next; } anchor = &(ixewk->next); } if( rswk->u.refb.hblk->prt_term != NULL ) { ixewk = fill_ix_e_blk( anchor, ixhwk, pgvalue, rswk->u.refb.hblk->prt_term, rswk->u.refb.hblk->prt_term_len ); } else { ixewk = fill_ix_e_blk( anchor, ixhwk, pgvalue, rswk->u.refb.hblk->ix_term, rswk->u.refb.hblk->ix_term_len ); } } } } if( idseen ) { // ID specified create reference entry reid.u.refb.hblk = ixhwk; reid.u.refb.eblk = ixewk; reid.flags = rf_ix; refwork = mem_alloc( sizeof( reid ) ); memcpy( refwork, &reid, sizeof( reid ) ); add_ref_entry( &iref_dict, refwork ); } if( pgtext != NULL ) { mem_free( pgtext ); } if( printtxt != NULL ) { mem_free( printtxt ); } if( seetext != NULL ) { mem_free( seetext ); } scan_start = scan_stop + 1; return; }
void scr_ix( void ) { condcode cc; // resultcode from getarg() static char cwcurr[4] = {" ix"};// control word string for errmsg int lvl; // max index level in control word data int k; int comp_len;// compare length for searching existing entries int comp_res; // compare result char * ix[3]; // index string(s) to add uint32_t ixlen[3]; // corresponding lengths ix_h_blk * * ixhwork; // anchor point for insert ix_h_blk * ixhwk; // index block ix_h_blk * ixhcurr[3]; // active index heading block per lvl ix_e_blk * ixewk; // index entry block bool do_nothing; // true if index string duplicate uint32_t wkpage; scan_restart = scan_stop + 1; if( !(GlobalFlags.index && GlobalFlags.lastpass) ) { return; // no need to process .ix } // no index wanted or not lastpass cwcurr[0] = SCR_char; lvl = 0; // index level // if( ProcFlags.page_started ) { // wkpage = page; // } else { wkpage = page + 1; // not quite clear TBD // } garginit(); // over control word while( lvl < 3 ) { // try to get 3 lvls of index cc = getarg(); if( cc == omit || cc == quotes0 ) { // no (more) arguments if( lvl == 0 ) { parm_miss_err( cwcurr ); return; } else { break; } } else { if( *tok_start == '.' && arg_flen == 1 ) { if( lvl > 0 ) { xx_opt_err( cwcurr, tok_start ); break; // .ix s1 s2 . ref format not supprted } cc = getarg(); if( cc == pos || cc == quotes ) { // .ix . dump ??? if( arg_flen == 4 ) { if( !strnicmp( tok_start, "DUMP", 4 ) ) { ixdump( index_dict ); break; } } xx_opt_err( cwcurr, tok_start );// unknown option } else { parm_miss_err( cwcurr ); return; } break; // no index entry text } ix[lvl] = tok_start; *(tok_start + arg_flen) = 0; ixlen[lvl] = arg_flen; lvl++; } } cc = getarg(); /***************************************************************************/ /* The docu says .ix "I1" "I2" "I3" "extra" is invalid, but WGML4 accepts */ /* it without error and processes it like the :I3 pg="extra" attribute */ /***************************************************************************/ // if( cc != omit ) { // parm_extra_err( cwcurr, tok_start - (cc == quotes) ); // return; // } if( lvl > 0 ) { // we have at least one index string ixhwork = &index_dict; for( k = 0; k < lvl; ++k ) { do_nothing = false; while( *ixhwork != NULL ) { // find alfabetic point to insert comp_len = ixlen[k]; if( comp_len > (*ixhwork)->ix_term_len ) comp_len = (*ixhwork)->ix_term_len; ++comp_len; comp_res = strnicmp( ix[k], (*ixhwork)->ix_term, comp_len ); if( comp_res > 0 ) { // new is later in alfabet ixhwork = &((*ixhwork)->next); continue; } if( comp_res == 0 ) { // equal if( ixlen[k] == (*ixhwork)->ix_term_len ) { do_nothing = true; break; // entry already there } if( ixlen[k] > (*ixhwork)->ix_term_len ) { ixhwork = &((*ixhwork)->next); continue; // new is longer } } break; // insert point reached } if( !do_nothing ) { // insert point reached ixhwk = mem_alloc( sizeof( ix_h_blk ) ); ixhwk->next = *ixhwork; ixhwk->ix_lvl= k + 1; ixhwk->lower = NULL; ixhwk->entry = NULL; ixhwk->prt_term = NULL; ixhwk->prt_term_len = 0; ixhwk->ix_term_len = ixlen[k]; ixhwk->ix_term = mem_alloc( ixlen[k] + 1 ); strcpy_s( ixhwk->ix_term, ixlen[k] + 1, ix[k] ); *ixhwork = ixhwk; } else { // string already in dictionary at this level ixhwk = *ixhwork; } ixhcurr[lvl] = ixhwk; if( k < lvl ) { ixhwork = &(ixhwk->lower); // next lower level } } // now add the pageno to index entry if( ixhwk->entry == NULL ) { // first pageno for entry /***************************************************************************/ /* The docu says .ix "I1" "I2" "I3" "extra" is invalid, but WGML4 accepts */ /* it without error and processes it like the :I3 pg="extra" attribute */ /* try to process the extra parm */ /***************************************************************************/ if( cc != omit ) { *(tok_start + arg_flen) = 0; fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgstring, tok_start, arg_flen ); } else { fill_ix_e_blk( &(ixhwk->entry), ixhwk, pgpageno, NULL, 0 ); } } else { ixewk = ixhwk->entry; while( ixewk->next != NULL ) { // find last entry ixewk = ixewk->next; } if( (ixewk->entry_typ >= pgstring) || (ixewk->page_no != wkpage) ) { // if last entry doesn't point to current page create entry if( cc != omit ) { *(tok_start + arg_flen) = 0; fill_ix_e_blk( &(ixewk->next), ixhwk, pgstring, tok_start, arg_flen ); } else { fill_ix_e_blk( &(ixewk->next), ixhwk, pgpageno, NULL, 0 ); } } } } return; }