#!/usr/bin/awk -f
############
# CHANGELOG
#===========
# 2010/03/24    CRMS00221778    Thanh lam NGUYEN
#               Add 1st version, from getXML.awk from 'LAWKER'.
#               remove integrated doc.
################

func help( name )
{
    sub( /^.*\//, "", name )
    print "SYNTAX: "name" [help][list=1][all=1][platform=1][ict=1][debug=1] <XML_FILE> [[<xml_path>|<xml_tag>|<xml_attribute>] ...]"
    print ""
    print "Retrieve information from an XML file."
    print "The return format is in the format 'name=\"value\"' double quote included."
    print "Any double quote inside the value is escaped with '\\'."
    print ""
    print "Where:"
    printf "%10s  %s\n",     "help", "Display this help."
    print ""
    printf "%10s  %s\n",     "list", "When set to '1', list the <path>|<tag>|<attributes> from the xml file that are setted."
    printf "%10s  %s\n",         "", "Default: 0."
    print ""
    printf "%10s  %s\n",      "all", "When set to '1', get all the <tag>s that are setted in the form <tag>=\"<value>\"."
    printf "%10s  %s\n",         "", "Default: 0."
    print ""
    printf "%10s  %s\n",      "ict", "When set to '1', interpret settings from xml file describing settings for the ICTouch phone set."
    printf "%10s  %s\n",         "", "I.e the name of the setting is in the 'id' attribute and the value in 'value' attribute."
    printf "%10s  %s\n",         "", "Default: 0."
    print ""
    printf "%10s  %s\n", "platform", "When set to '1', work only on platform settings (imply ict=1). The content of 'id' attribute is"
    printf "%10s  %s\n",         "", "modified to according to the rule between the platform settings and the offical setting names."
    printf "%10s  %s\n",         "", "I.e 'DmEnetcfgSipFile' becomes 'ENETCFG_SIP_FILE'."
    printf "%10s  %s\n",         "", "Default: 0."
    print ""
}

func printstderr( str )
{
    if (!debug)
        return
    print str > "/dev/stderr"
}

func getIdDisplay( attr )
{
    if ( !platform || (platform && !match(attr, /^(Local|Dhcp|Lldp|Dm|Current)/)))
        return attr
    gsub( /[A-Z]/, "_&", attr )
    attr=toupper(attr)
    sub( /^_(LOCAL_|DHCP_|LLDP_|DM_|CURRENT_)*/, "", attr )
    return attr
}
func displayListItem( format, name, path, _tmp )
{
    printstderr("[32mdisplayListItem("format", "name","path")[0m")
    _tmp=name
    sub( /^.*\//, "", _tmp )
    if (platform) {
        if (match(_tmp, /^(Local|Dhcp|Lldp|Dm|Current)/)) {
            name=getIdDisplay(name)
            printf( format"\n", name, " ( path: "path" )" )
        }
    } else {
        printf( format"\n", name, " ( path: "path" )" )
    }
}
func display( name, value )
{
    printstderr("[32mdisplay("name","value")[0m")
    if (name=="")
        return
    if ( !platform || (platform && match(name, /^(Local|Dhcp|Lldp|Dm|Current)/))) {
        if (platform)
            name=getIdDisplay(name)
        # removing leading spaces on all lines
        gsub(/\n[[:blank:]]*/, "\n", value)
        # escaping '"'
        gsub(/[\\\"]/, "\\\\&", value)
        print name"=\""value"\""
    }
}

BEGIN {
    ########
    # PROCESS ARGUMENT LINE
    ########################
    xmlFile=""
    found=1
    list=0
    platform=0
    all=0
    printstderr(sprintf("[32mARGC: %d[0m", ARGC))
    for(i=1; i<ARGC; i++) {
        printstderr("[32mARG["ARGV[i]"][0m")
        if (ARGV[i]=="help") {
            help(ARGV[0])
            exit 0
        }
        if (index(ARGV[i], "=")) {
            # an option
            printstderr("[32mOPTION: "ARGV[i]"[0m")
            if (ARGV[i]=="list=1") {
                printstderr("[32m\tlist[0m")
                list=1
            } else if (ARGV[i]=="debug=1") {
                printstderr("[32m\tdebug[0m")
                debug=1
            } else if (ARGV[i]=="platform=1") {
                printstderr("[32m\tplatform[0m")
                platform=1
                ict=1
            } else if (ARGV[i]=="ict=1") {
                printstderr("[32m\tict[0m")
                ict=1
            } else if (  ARGV[i]=="all=1" ) {
                printstderr("[32m\tall[0m")
                all=1
            }
            continue
        }
        if (xmlFile=="") {
            printstderr("[32mXML FILE="ARGV[i]"[0m")
            xmlFile=ARGV[i]
        } else {
            _tmp=ARGV[i]
            sub(/^\//, "", _tmp)
            printstderr("[32mAdding item "_tmp"[0m")
            item[_tmp]=""
        }
    }
    if (debug) {
        _tmp=""
        for (i in item)
            _tmp=_tmp" "i
        printstderr("[32mitems:"_tmp"[0m")
    }
    ########
    # PARSE XML FILE
    #################
    printstderr("[32m=================== End of command line parsing ===================[0m")
    tag=attr=value=""
    while (getXML(xmlFile, 0)) {
        printstderr("[34m"XTYPE"\t"XITEM"\t"XPATH"[0m")
        tag=XITEM
        if (XTYPE=="TAG") {
            ######
            # TAG
            ######
            printstderr("[32m"XTYPE"\t"XITEM"[0m")
            printstderr("[31m\tpath="XPATH"[0m")
            printstderr("[31m\ttag="tag"[0m")
            # process attributes
            #####################
            for (_attr in XATTR) {
                printstderr("[32m\t\tattribute: "_attr" ("XATTR[_attr]")[0m")
                if (list) {
                    printstderr("[32m\t\tlist "_attr"[0m")
                    if (!ict) 
                        displayListItem("%-30s%s", tag"."_attr, XPATH"."_attr)
                    if (ict && _attr == "id" ) {
                        _id=XATTR["id"]
                        printstderr( "[32m\t\tlist "_id"[0m" )
                        displayListItem("%-30s%s", _id, _id)
                    }
                } else if (all && !ict) {
                    display( tag"."_attr, XATTR[_attr] )
                }
                if (!ict && ( XPATH"."_attr in item || tag"."_attr in item || _attr in item )) {
                    printstderr( "[32m\t\tfound '"_attr"' in item[0m" )
                    attr=tag"."_attr
                    value=XATTR[_attr]
                }
                if (ict && _attr=="id" ) {
                    printstderr( "[32m\t\tfound 'id' in item[0m" )
                    attr=XATTR["id"]
                    value=XATTR["value"]
                }
            }
            # attributes
            #############
        } else if ( XTYPE=="DAT" ) {
            ###########
            # TAG DATA
            ###########
            printstderr( "[32m"XTYPE"\t(path="XPATH")"XITEM"[0m" )
            _value=XITEM
            gsub( /\n[[:space:]]*/, "\n", _value )
            # remove leading '\n'
            gsub( /^\n/, "", _value )
            # remove trailing '\n'
            gsub( /\n$/, "", _value )
            tagvalue[XPATH]=tagvalue[XPATH]""_value
            printstderr( "[32m\t(tagvalue="tagvalue[XPATH]")[0m" )
        } else if ( XTYPE=="END" ) {
            ##########
            # TAG END
            ##########
            printstderr( "[32m"XTYPE"\t("XITEM")[0m" )
            # display found information
            if (list) {
                if ( tagvalue[XPATH"/"tag] != "" )
                    displayListItem("%-30s%s", tag, XPATH"/"tag )
            } else if (all) {
                if (!ict && tagvalue[XPATH"/"tag] != "") {
                    display( tag, tagvalue[XPATH"/"tag] )
                }
                display( attr, value )
            } else {
                if ( XPATH in item || tag in item )
                    display( tag, tagvalue[XPATH"/"tag] )
                if ( XPATH"/"tag"."attr in item || tag"."attr in item || attr in item )
                    display( attr, value )
            }
            attr=value=""
            delete tagvalue[XPATH"/"tag]
        }
    }
    if (XERROR) {
        printstderr( XERROR )
        exit 1
    }
    exit found
}
function getXML( file, skipData           \
				,end,p,q,tag,att,accu,mline,mode,S0,ex,dtd) {
    XTYPE=XITEM=XERROR=XNODE=""; split("",XATTR);
    S0=_XMLIO[file,"S0"]; XLINE=_XMLIO[file,"line"];
	XPATH=_XMLIO[file,"path"]; dtd=_XMLIO[file,"dtd"];
    while (!XTYPE) {
        if (S0=="") { if (1!=(getline S0 <file)) break; XLINE++; S0=S0 RS; }
        if ( mode == "" ) {
            mline=XLINE; accu=""; p=substr(S0,1,1);
            if ( p!="<" && !(dtd && p=="]") )
				mode="DAT";
            else if ( p=="]" )
				{ S0=substr(S0,2);  mode="DTE"; end=">"; dtd=0; }
            else if ( substr(S0,1,4)=="<!--" )
				{ S0=substr(S0,5);  mode="COM"; end="-->"; }
            else if ( substr(S0,1,9)=="<!DOCTYPE" )
                { S0=substr(S0,10); mode="DTB"; end=">"; }
            else if ( substr(S0,1,9)=="<![CDATA[" )
                { S0=substr(S0,10); mode="CDA"; end="]]>"; }
            else if ( substr(S0,1,2)=="<!" )
				{ S0=substr(S0,3);  mode="DEC"; end=">"; }
            else if ( substr(S0,1,2)=="<?" )
				{ S0=substr(S0,3);  mode="PIN"; end="?>"; }
            else if ( substr(S0,1,2)=="</" )
				{ S0=substr(S0,3);  mode="END"; end=">";
                tag=S0;sub(/[ \n\r\t>].*$/,"",tag);
				S0=substr(S0,length(tag)+1);
                ex=XPATH;sub(/\/[^\/]*$/,"",XPATH);
				ex=substr(ex,length(XPATH)+2);
                if (tag!=ex) {
                   	XERROR="unexpected close tag <" ex ">..</" tag ">";
					break; } }
            else{
				S0=substr(S0,2);  mode="TAG";
                tag=S0;sub(/[ \n\r\t\/>].*$/,"",tag);
				S0=substr(S0,length(tag)+1);
                if ( tag !~ /^[A-Za-z:_][0-9A-Za-z:_.-]*$/ ) {
                    XERROR="invalid tag name '" tag "'"; break; }
                XPATH = XPATH "/" tag; } }
        else if ( mode == "DAT" ) {
            p=index(S0,"<");
			if ( dtd && (q=index(S0,"]")) && (!p || q<p) ) p=q;
            if (p) {
                if (!skipData) { XTYPE="DAT";
                       XITEM=accu unescapeXML(substr(S0,1,p-1)); }
                S0=substr(S0,p); mode=""; }
            else{ if (!skipData) accu=accu unescapeXML(S0); S0=""; } }
        else if ( mode == "TAG" ) {
			sub(/^[ \n\r\t]*/,"",S0); if (S0=="") continue;
            if ( substr(S0,1,2)=="/>" ) {
                S0=substr(S0,3); mode=""; XTYPE="TAG";
				XITEM=tag; S0="</"tag">"S0; }
            else if ( substr(S0,1,1)==">" ) {
                S0=substr(S0,2); mode=""; XTYPE="TAG"; XITEM=tag; }
            else{
                att=S0; sub(/[= \n\r\t\/>].*$/,"",att);
				S0=substr(S0,length(att)+1); mode="ATTR";
                if ( att !~ /^[A-Za-z:_][0-9A-Za-z:_.-]*$/ ) {
                    XERROR="invalid attribute name '" att "'";
					break; } } }
        else if ( mode == "ATTR" ) {
				sub(/^[ \n\r\t]*/,"",S0); if (S0=="") continue;
            if ( substr(S0,1,1)=="=" ) { S0=substr(S0,2); mode="EQ"; }
            else                       { XATTR[att]=att; mode="TAG";
                                         XNODE=XNODE att"="att"\001"; } }
        else if ( mode == "EQ" ) {
					sub(/^[ \n\r\t]*/,"",S0); if (S0=="") continue;
            end=substr(S0,1,1);
            if ( end=="\"" || end=="'" ) {
					S0=substr(S0,2);accu="";mode="VALUE";}
            else{
                accu=S0; sub(/[ \n\r\t\/>].*$/,"",accu);
				S0=substr(S0,length(accu)+1);
                XATTR[att]=unescapeXML(accu); mode="TAG";
				XNODE=XNODE att"="XATTR[att]"\001"; } }
        else if ( mode == "VALUE" ) { # terminated by end
            if ( p=index(S0,end) ) {
                XATTR[att]=accu unescapeXML(substr(S0,1,p-1));
				XNODE=XNODE att"="XATTR[att]"\001";
                S0=substr(S0,p+length(end)); mode="TAG"; }
            else{ accu=accu unescapeXML(S0); S0=""; } }
        else if ( mode == "DTB" ) { # terminated by "[" or ">"
            if ( (q=index(S0,"[")) && (!(p=index(S0,end)) || q<p ) ) {
                XTYPE=mode; XITEM= accu substr(S0,1,q-1);
				S0=substr(S0,q+1); mode=""; dtd=1; }
            else if ( p=index(S0,end) ) {
                XTYPE=mode; XITEM= accu substr(S0,1,p-1);
				S0="]"substr(S0,p); mode=""; dtd=1; }
            else{ accu=accu S0; S0=""; } }
        else if ( p=index(S0,end) ) {  # terminated by end
            XTYPE=mode; XITEM= ( mode=="END" ? tag : accu substr(S0,1,p-1) );
            S0=substr(S0,p+length(end)); mode=""; }
        else{ accu=accu S0; S0=""; } }
    _XMLIO[file,"S0"]=S0; _XMLIO[file,"line"]=XLINE;
	_XMLIO[file,"path"]=XPATH; _XMLIO[file,"dtd"]=dtd;
    if (mode=="DAT") { mode=""; if (accu!="") XTYPE="DAT"; XITEM=accu; }
    if (XTYPE) { XNODE=XTYPE"\001"XITEM"\001"XNODE; return 1; }
    close(file);
    delete _XMLIO[file,"S0"]; delete _XMLIO[file,"line"];
	delete _XMLIO[file,"path"]; delete _XMLIO[file,"dtd"];
    if (XERROR) XERROR=file ":" XLINE ": " XERROR;
    else if (mode) XERROR=file ":" mline ": " "unterminated " mode;
    else if (XPATH) XERROR=file ":" XLINE ": "  "unclosed tag(s) " XPATH;
}
function unescapeXML( text ) {
    gsub( "&apos;", "'",  text );
    gsub( "&quot;", "\"", text );
    gsub( "&gt;",   ">",  text );
    gsub( "&lt;",   "<",  text );
    gsub( "&amp;",  "\\&",  text );
    return text
}
function closeXML( file ) {
    close(file);
    delete _XMLIO[file,"S0"]; delete _XMLIO[file,"line"];
    delete _XMLIO[file,"path"]; delete _XMLIO[file,"dtd"];
    delete _XMLIO[file,"open"]; delete _XMLIO[file,"IND"];
}

