void scr_th( void ) { ifcb * cb = input_cbs->if_cb; char linestr[MAX_L_AS_STR]; scan_err = false; cb->if_flags[cb->if_level].ifcwte = false; if( !cb->if_flags[cb->if_level].iflast || !(cb->if_flags[cb->if_level].iftrue || cb->if_flags[cb->if_level].iffalse) || cb->if_flags[cb->if_level].ifthen || cb->if_flags[cb->if_level].ifelse || cb->if_flags[cb->if_level].ifdo ) { scan_err = true; g_err( err_if_then ); if( input_cbs->fmflags & II_macro ) { ultoa( input_cbs->s.m->lineno, linestr, 10 ); g_info( inf_mac_line, linestr, input_cbs->s.m->mac->name ); } else { ultoa( input_cbs->s.f->lineno, linestr, 10 ); g_info( inf_file_line, linestr, input_cbs->s.f->filename ); } show_ifcb( "then", cb ); show_include_stack(); err_count++; return; } cb->if_flags[cb->if_level].iflast = false; cb->if_flags[cb->if_level].ifthen = true; ProcFlags.keep_ifstate = true; if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "then", cb ); } garginit(); // find end of control word while( *scan_start == ' ' ) { scan_start++; } if( *scan_start ) { // rest of line is not empty split split_input( buff2, scan_start, false );// and process next } scan_restart = scan_stop + 1; return; }
void scr_th( void ) { ifcb * cb = input_cbs->if_cb; scan_err = false; cb->if_flags[cb->if_level].ifcwte = false; if( !cb->if_flags[cb->if_level].iflast || !(cb->if_flags[cb->if_level].iftrue || cb->if_flags[cb->if_level].iffalse) || cb->if_flags[cb->if_level].ifthen || cb->if_flags[cb->if_level].ifelse || cb->if_flags[cb->if_level].ifdo ) { scan_err = true; g_err( err_if_then ); g_info_inp_pos(); show_ifcb( "then", cb ); show_include_stack(); err_count++; return; } cb->if_flags[cb->if_level].iflast = false; cb->if_flags[cb->if_level].ifthen = true; ProcFlags.keep_ifstate = true; if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "then", cb ); } garginit(); // find end of control word while( *scan_start == ' ' ) { scan_start++; } if( *scan_start ) { // rest of line is not empty split split_input( buff2, scan_start, false );// and process next } scan_restart = scan_stop; return; }
void scr_pu( void ) { int workn; condcode cc; char * p; garginit(); // find end of CW cc = getarg(); // workfile number if( cc == omit ) { numb_err(); // we need workfile number return; } p = tok_start; if( (arg_flen > 1) || (*p < '1') || (*p > '9') ) { numb_err(); return; } workn = *p - '0'; scan_restart = scan_stop; cc = getarg(); // text follows if( cc == omit ) { // no then close workfile close_pu_file( workn ); return; } open_pu_file( workn ); // open if not already done fputs( tok_start, workfile[workn - 1] ); fputc( '\n', workfile[workn - 1] ); return; }
void scr_go( void ) { condcode cc; getnum_block gn; labelcb * golb; int k; char linestr[MAX_L_AS_STR]; input_cbs->if_cb->if_level = 0; // .go terminates ProcFlags.keep_ifstate = false; // ... all .if controls garginit(); cc = getarg(); if( cc != pos ) { scan_err = true; err_count++; g_err( err_missing_name, "" ); if( input_cbs->fmflags & II_tag_mac ) { utoa( input_cbs->s.m->lineno, linestr, 10 ); g_info( inf_mac_line, linestr, input_cbs->s.m->mac->name ); } else { utoa( input_cbs->s.f->lineno, linestr, 10 ); g_info( inf_file_line, linestr, input_cbs->s.f->filename ); } show_include_stack(); return; } gn.argstart = tok_start; gn.argstop = scan_stop; gn.ignore_blanks = 0; cc = getnum( &gn ); // try numeric expression evaluation if( cc == pos || cc == neg) { // numeric linenumber gotarget[0] = '\0'; // no target label name if( gn.num_sign == ' ' ) { // absolute number gotargetno = gn.result; } else { if( input_cbs->fmflags & II_tag_mac ) { gotargetno = input_cbs->s.m->lineno; } else { gotargetno = input_cbs->s.f->lineno; } gotargetno += gn.result; // relative target line number } if( gotargetno < 1 ) { scan_err = true; err_count++; g_err( err_label_zero ); if( input_cbs->fmflags & II_tag_mac ) { utoa( input_cbs->s.m->lineno, linestr, 10 ); g_info( inf_mac_line, linestr, input_cbs->s.m->mac->name ); } else { utoa( input_cbs->s.f->lineno, linestr, 10 ); g_info( inf_file_line, linestr, input_cbs->s.f->filename ); } show_include_stack(); return; } if( input_cbs->fmflags & II_tag_mac ) { if( gotargetno <= input_cbs->s.m->lineno ) { input_cbs->s.m->lineno = 0; // restart from beginning input_cbs->s.m->macline = input_cbs->s.m->mac->macline; } } } else { // no numeric target label gotargetno = 0; // no target lineno known if( arg_flen > MAC_NAME_LENGTH ) { err_count++; g_err( err_sym_long, tok_start ); if( input_cbs->fmflags & II_tag_mac ) { utoa( input_cbs->s.m->lineno, linestr, 10 ); g_info( inf_mac_line, linestr, input_cbs->s.m->mac->name ); } else { utoa( input_cbs->s.f->lineno, linestr, 10 ); g_info( inf_file_line, linestr, input_cbs->s.f->filename ); } show_include_stack(); arg_flen = MAC_NAME_LENGTH; } for( k = 0; k < MAC_NAME_LENGTH; k++ ) {// copy to work gotarget[k] = *tok_start++; } gotarget[k] = '\0'; golb = find_label( gotarget ); if( golb != NULL ) { // label already known gotargetno = golb->lineno; if( input_cbs->fmflags & II_tag_mac ) { if( golb->lineno <= input_cbs->s.m->lineno ) { input_cbs->s.m->lineno = 0; // restart from beginning input_cbs->s.m->macline = input_cbs->s.m->mac->macline; } } else { if( golb->lineno <= input_cbs->s.f->lineno ) { fsetpos( input_cbs->s.f->fp, &golb->pos ); input_cbs->s.f->lineno = golb->lineno - 1;// position file } } } } free_lines( input_cbs->hidden_head ); // delete split line input_cbs->hidden_head = NULL; input_cbs->hidden_tail = NULL; ProcFlags.goto_active = true; // special goto processing scan_restart = scan_stop + 1; }
void scr_gt( void ) { char * p; char * pn; char savetag; int k; int len; char macname[MAC_NAME_LENGTH + 1]; condcode cc; gtentry * wk; gtflags tag_flags; enum { f_add = 1, f_change, f_delete, f_off, f_on, f_print } function; garginit(); // find end of CW /***********************************************************************/ /* isolate tagname or use previous if tagname * */ /***********************************************************************/ cc = getarg(); // Tagname if( cc == omit ) { // no operands tag_name_missing_err(); return; } p = tok_start; if( *p == '*' ) { // single * as tagname if( arg_flen > 1 ) { xx_err( err_tag_name_inv ); return; } savetag = '*'; // remember for possible global delete / print if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) { if( tag_entry != NULL ) { out_msg(" using tagname %s %s\n", tagname, tag_entry->name ); } } } else { savetag = ' '; // no global function for delete / print init_tag_att(); // forget previous values for quick access attname[0] = '*'; pn = tagname; len = 0; while( *p && is_macro_char( *p ) ) { if( len < TAG_NAME_LENGTH ) { *pn++ = tolower( *p++ );// copy lowercase tagname *pn = '\0'; } else { break; } len++; } for( k = len; k < TAG_NAME_LENGTH; k++ ) { tagname[k] = '\0'; } tagname[TAG_NAME_LENGTH] = '\0'; if( len < arg_flen ) { xx_err( err_tag_name_inv ); return; } } /***********************************************************************/ /* get function operand add, change, ... */ /***********************************************************************/ cc = getarg(); if( cc == omit ) { xx_err( err_tag_func_inv ); return; } p = tok_start; function = 0; switch( tolower( *p ) ) { case 'a': if( !strnicmp( "ADD ", p, 4 ) ) { function = f_add; } break; case 'c' : if( (arg_flen > 2) && (arg_flen < 7) && !strnicmp( "CHANGE", p, arg_flen ) ) { function = f_change; } break; case 'o' : if( !strnicmp( "OFF", p, 3 ) ) { function = f_off; } else { if( !strnicmp( "ON", p, 2 ) ) { function = f_on; } } break; case 'd' : if( (arg_flen > 2) && (arg_flen < 7) && !strnicmp( "DELETE", p, arg_flen ) ) { function = f_delete; } break; case 'p' : if( (arg_flen > 1) && (arg_flen < 6) && !strnicmp( "PRINT", p, arg_flen ) ) { function = f_print; } break; default: // nothing break; } if( function == 0 ) { // no valid function specified xx_err( err_tag_func_inv ); return; } cc = getarg(); // get possible next parm /***********************************************************************/ /* for add and change get macroname */ /***********************************************************************/ if( function == f_add || function == f_change ) { // need macroname if( cc == omit ) { xx_err( err_tag_mac_name ); return; } p = tok_start; pn = macname; len = 0; while( *p && is_macro_char( *p ) ) { if( len < MAC_NAME_LENGTH ) { *pn++ = tolower( *p++ ); // copy lowercase macroname *pn = '\0'; } else { break; } len++; } for( k = len; k < MAC_NAME_LENGTH; k++ ) { macname[k] = '\0'; } macname[MAC_NAME_LENGTH] = '\0'; tag_flags = 0; if( function == f_add ) { // collect tag options cc = scan_tag_options( &tag_flags ); if( cc != omit ) { // not all processed error xx_err( err_tag_opt_inv ); } tag_entry = add_tag( &tag_dict, tagname, macname, tag_flags ); // add to dictionary // if tag_entry is now NULL, error (+ msg) was output in add_tag } else { // is function change tag_entry = change_tag( &tag_dict, tagname, macname ); } } else { /***********************************************************************/ /* after delete, off, on, print nothing allowed */ /***********************************************************************/ if( cc != omit ) { xx_err( err_tag_toomany ); // nothing more allowed } switch( function ) { case f_print : if( savetag == '*' ) { print_tag_dict( tag_dict ); } else { print_tag_entry( find_tag( &tag_dict, tagname ) ); } break; case f_delete : if( savetag == '*' ) { free_tag_dict( &tag_dict ); } else { free_tag( &tag_dict, find_tag( &tag_dict, tagname ) ); } break; case f_off : if( savetag == '*' && tag_entry != NULL ) {// off for last defined tag_entry->tagflags |= tag_off; } else { wk = find_tag( &tag_dict, tagname ); if( wk != NULL ) { wk->tagflags |= tag_off; } } break; case f_on : if( savetag == '*' && tag_entry != NULL ) {// on for last defined tag_entry->tagflags |= tag_off; } else { wk = find_tag( &tag_dict, tagname ); if( wk != NULL ) { wk->tagflags &= ~tag_off; } } break; default: break; } } scan_restart = scan_stop +1; return; }
void scr_do( void ) { ifcb * cb = input_cbs->if_cb; condcode cc; scan_err = false; garginit(); // find end of control word cc = getarg(); cb->if_flags[cb->if_level].ifcwdo = false; if( cc == omit || !strnicmp( tok_start, "begin", 5 )) { if( !(cb->if_flags[cb->if_level].ifthen || cb->if_flags[cb->if_level].ifelse) || cb->if_flags[cb->if_level].ifdo ) { scan_err = true; g_err( err_if_do ); g_info_inp_pos(); show_ifcb( "dobegin", cb ); show_include_stack(); err_count++; return; } cb->if_flags[cb->if_level].ifdo = true; if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "dobegin", cb ); } scan_restart = scan_stop; return; } else { if( !strnicmp( tok_start, "end", 3 )) { if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "doend", cb ); } do { // loop for last active .do begin if( cb->if_flags[cb->if_level].ifdo ) { cb->if_flags[cb->if_level].ifdo = false; if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "doend", cb ); } scan_restart = scan_stop; return; } if( cb->if_flags[cb->if_level].ifthen || cb->if_flags[cb->if_level].ifelse || !(cb->if_flags[cb->if_level].iftrue || cb->if_flags[cb->if_level].iffalse) ) { scan_err = true; g_err( err_if_do_end ); g_info_inp_pos(); show_ifcb( "doend", cb ); show_include_stack(); err_count++; return; } } while( cb->if_level-- > 0 ); #if 0 if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { out_msg( "\t.do end Level %d\n" "\t.ifcb iftrue %d, iffalse %d\n", cb->if_level, cb->if_flags[cb->if_level].iftrue, cb->if_flags[cb->if_level].iffalse ); } #endif } else { scan_err = true; g_err( err_if_do_fun ); g_info_inp_pos(); show_include_stack(); err_count++; return; } } if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "do xx", cb ); } scan_restart = scan_stop; return; }
void scr_if( void ) { ifcb * cb; // if stack ptr condcode cct1; condcode cct2; condcode ccrelop; termcb t1; // first argument termcb t2; // second argument relop relation; // the relation between t1 and t2 logop logical; // if more than 1 condition bool ifcond; // current condition bool totalcondition; // resultant condition bool firstcondition; // first comparison .if scan_err = false; firstcondition = true; // first 2 terms to compare garginit(); // find end of control word cb = input_cbs->if_cb; // get .if control block cb->if_flags[cb->if_level].ifcwif = false; // reset cwif switch for( ;; ) { // evaluate if conditions cct1 = gargterm( &t1 ); // get term 1 ccrelop = gargrelop( &relation ); // get relation operator cct2 = gargterm( &t2 ); // get term 2 if( (cct1 == no) || (cct2 == no) ) { scan_err = true; err_count++; g_err( err_if_term ); g_info_inp_pos(); show_include_stack(); return; } if( ccrelop != pos ) { scan_err = true; err_count++; g_err( err_if_relop ); g_info_inp_pos(); show_include_stack(); return; } // terms and operator ok now compare ifcond = ifcompare( &t1, relation, &t2 ); mem_free( t1.term_string ); // don't need the strings anymore mem_free( t2.term_string ); if( firstcondition ) { firstcondition = false; if( cb->if_level < MAX_IF_LEVEL ) { cb->if_level++; memset( &cb->if_flags[cb->if_level], '\0', sizeof( cb->if_flags[cb->if_level] ) ); cb->if_flags[cb->if_level].iflast = true; cb->if_flags[cb->if_level].ifcwte = false; // no .th .el yet cb->if_flags[cb->if_level].iftrue = false; // cond not yet true cb->if_flags[cb->if_level].iffalse = false; // cond not yet false } else { scan_err = true; g_err( err_if_nesting ); g_info_inp_pos(); show_include_stack(); err_count++; return; } totalcondition = ifcond; } else { // resultant condition if( logical == AND ) { totalcondition &= ifcond; } else { totalcondition |= ifcond; } } if( totalcondition ) { // set if true / false flags cb->if_flags[cb->if_level].iftrue = true; cb->if_flags[cb->if_level].iffalse = false; } else { cb->if_flags[cb->if_level].iffalse = true; cb->if_flags[cb->if_level].iftrue = false; } while( *scan_start == ' ' ) { scan_start++; } /* * test logical condition if not line end * .if a = b or c GT d * ^^ */ if( *scan_start ) { if( *scan_start == SCR_char ) { break; // .xx can't be logical operator } if( *(scan_start + 1) == ' ' ) {// single char + blank if( *scan_start == '&' ) { logical = AND; scan_start += 2; continue; // do next conditions } else if( *scan_start == '|' ) { logical = OR; scan_start += 2; continue; // do next conditions } } else { if( !strnicmp( scan_start, "and ", 4 ) ) { logical = AND; scan_start += 4; continue; // do next conditions } else if( !strnicmp( scan_start, "or ", 3 ) ) { logical = OR; scan_start += 3; continue; // do next conditions } } } break; // no more operators / conditions } if( cb->if_level > 1 ) { // nested if if( cb->if_flags[cb->if_level - 1].ifthen ) { // object of .th if( cb->if_flags[cb->if_level - 1].iffalse ) {// last .if false cb->if_flags[cb->if_level].iftrue = true;// process nothing cb->if_flags[cb->if_level].iffalse = true; } } else { if( cb->if_flags[cb->if_level - 1].ifelse // object of .el && cb->if_flags[cb->if_level - 1].iftrue ) {// last .if true cb->if_flags[cb->if_level].iftrue = true;// process nothing cb->if_flags[cb->if_level].iffalse = true; } } } if( input_cbs->fmflags & II_research && GlobalFlags.firstpass ) { show_ifcb( "if", cb ); #if 0 out_msg( "\t.if is %s Level %d\n" "\t.ifcb iftrue %d, iffalse %d\n", totalcondition ? "true " : "false", cb->if_level, cb->if_flags[cb->if_level].iftrue, cb->if_flags[cb->if_level].iffalse ); #endif } if( *scan_start ) { // rest of line is not empty split_input( buff2, scan_start, false ); // split and process next } scan_restart = scan_stop; 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; }
void scr_ga( void ) { char * p; char * pn; char savetag; char saveatt; int k; int len; condcode cc; gaflags att_flags; gavalflags val_flags; gavalentry * gaval; gaentry * gawk; savetag = ' '; saveatt = ' '; att_flags = 0; val_flags = 0; garginit(); // find end of CW cc = getarg(); // Tagname or * if( cc == omit || (*tok_start == '*' && tag_entry == NULL) ) { // no operands or tagname * and no previous definition tag_name_missing_err(); } if( tag_entry == NULL ) { // error during previous .gt scan_restart = scan_stop + 1; // ignore .ga return; } /***********************************************************************/ /* isolate tagname use previous if tagname * */ /***********************************************************************/ p = tok_start; if( *p == '*' ) { // single * as tagname if( arg_flen > 1 ) { xx_err( err_tag_name_inv ); return; } savetag = '*'; // remember for possible quick access if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) { out_msg(" using tagname %s\n", tagname ); } } else { savetag = ' '; // no quick access init_tag_att(); // forget previous values for quick access pn = tagname; len = 0; while( *p && is_macro_char( *p ) ) { if( len < TAG_NAME_LENGTH ) { *pn++ = tolower( *p++ );// copy lowercase tagname *pn = '\0'; } else { break; } len++; } for( k = len; k < TAG_NAME_LENGTH; k++ ) { tagname[k] = '\0'; } tagname[TAG_NAME_LENGTH] = '\0'; if( len < arg_flen ) { xx_err( err_tag_name_inv );// name contains invalid or too many chars return; } tag_entry = find_tag( &tag_dict, tagname ); if( tag_entry == NULL ) { nottag_err(); // tagname not defined return; } } /***********************************************************************/ /* isolate attname use previous if attname * */ /***********************************************************************/ cc = getarg(); // Attribute name or * if( cc == omit || (*tok_start == '*' && att_entry == NULL) ) { // no operands or attname * and no previous definition xx_err( err_att_name_inv ); return; } p = tok_start; if( *p == '*' ) { // single * as attname if( arg_flen > 1 ) { xx_err( err_att_name_inv ); return; } saveatt = '*'; // remember for possible quick access if( GlobalFlags.firstpass && input_cbs->fmflags & II_research ) { out_msg(" using attname %s\n", attname ); } att_flags = att_entry->attflags; } else { saveatt = ' '; // no quick access att_entry = NULL; pn = attname; len = 0; while( *p && is_macro_char( *p ) ) { if( len < ATT_NAME_LENGTH ) { *pn++ = tolower( *p++ );// copy lowercase tagname *pn = '\0'; } else { break; } len++; } for( k = len; k < ATT_NAME_LENGTH; k++ ) { attname[k] = '\0'; } attname[ATT_NAME_LENGTH] = '\0'; if( len < arg_flen ) { xx_err( err_att_name_inv );// attname with invalid or too many chars cc = neg; return; } } /***********************************************************************/ /* process options A and options B */ /***********************************************************************/ if( cc != omit ) { if( saveatt != '*' ) { // no quickaccess for attribute gawk = NULL; for( gawk = tag_entry->attribs; gawk != NULL; gawk = gawk->next ) { if( !stricmp( attname, gawk->name ) ) { att_flags = gawk->attflags; // get possible uppercase option break; } } } else { att_flags = att_entry->attflags; } cc = scan_att_optionsA( &att_flags ); // process options A if( cc != omit ) { cc = scan_att_optionsB( &val_flags, cc, &att_flags );// process option B if( cc != omit ) { xx_err( err_tag_toomany ); // excess parameters return; } } } /***********************************************************************/ /* scanning complete add/modify attribute in dictionary */ /***********************************************************************/ if( saveatt != '*' ) { // no quickaccess for attribute for( att_entry = tag_entry->attribs; att_entry != NULL; att_entry = att_entry->next ) { if( !stricmp( attname, att_entry->name ) ) { break; } } } if( att_entry == NULL ) { // new attribute att_entry = mem_alloc( sizeof( gaentry ) ); att_entry->next = tag_entry->attribs; tag_entry->attribs = att_entry; att_entry->vals = NULL; att_entry->attflags = att_flags; strcpy( att_entry->name, attname ); } else { att_entry->attflags = att_flags;// update flags } gaval = mem_alloc( sizeof (gavalentry ) ); if( att_entry->vals == NULL ) { att_entry->vals = gaval; } else { gavalentry * valwk; for( valwk = att_entry->vals; valwk != NULL; valwk = valwk->next ) { if( valwk->next == NULL ) { break; // last entry found } } valwk->next = gaval; } gaval->next = NULL; gaval->valflags = val_flags; if( val_flags & val_length ) { gaval->a.length = ranges[0]; } else if( val_flags & val_range ) { for( k = 0; k < 4; k++ ) { gaval->a.range[k] = ranges[k]; } } else if( val_flags & val_value ) { strcpy_s( gaval->a.value, sizeof( gaval->a.value ), stringval ); } else if( val_flags & val_valptr ) { gaval->a.valptr = valptr; } scan_restart = scan_stop + 1; return; }