// The original script was written by  Jasper Bedaux (see copyright
// notice below). The changes are copyright by Volker H. Simonis 2007,
// who can be reached at http://www.progdoc.de/

// Following the copyright of the original script:
// -----------------------------------------------

// This JavaScript program is copyright by Jasper Bedaux (C) 2003.

// This script can be freely used and distributed as long as these
// copyright notices are preserved. If you use and or modify the script
// you have to mention the authors in a reasonable visible way.
// THIS SCRIPT COMES WITHOUT ANY WARRANTY OF ANY KIND.
// SELLING OF THIS SCRIPT IS NOT ALLOWED.
// 
// A link to http://www.bedaux.net/cpp2html/ will be appreciated.

// And here comes some documentation:
// ----------------------------------

// This script has been tested to work with: 
// Mozilla 1.7.12, Firefox 1.0.7, Konqueror 3.4.2, Opera 9.20 and
// Explorer 6 and 7

// Before you include this script, mak sure you have at least JavaScript 1.5
// available. This can be for example achieved like this:
// 
// <script language="Javascript1.5" type="text/javascript" src="highlight.js">
// </script>
//
// And here's a short example how you may use this script:
//
// - import it (see above)
//
// - place source code that should be highlighted inside a <pre> element that is
//   itself directly nested inside a <div> element with a class attribute that 
//   contains the value 'listing' like this:
//
//   <div class="listing cpp"><pre class="listing">
//   class cmpImovINode : public MachNode { 
//   private:
//     MachOper *_opnd_array[6];
//   public:
//   ...
//   </pre></div>
//
//   The highlight() function from this file will replace the <div> element
//   with a new <div> element that contains the highlighted source code. The
//   language of the source code can be specified as a second value of the class
//   attribute. Currently "cpp" for C++ and "java" are supported ("cpp" is the
//   default, if no language is explicitely choosen).
//
//   Notice that the highlight() function will copy and paste the <pre> tag as
//   it is from your document to the generated, highlighted code. So in the
//   example above, you could generate a certain kind of highlighting even if
//   this script shouldn't work (see notice below) if you define the following
//   style somwhere in the head section of your document:
//
//   <style type="text/css" id="internalStyle">
//     pre.listing {
//       display: table-cell;
//       color: black;
//       background-color: #F0F0FF;
//       border-style: solid;
//       border-width: 1px;
//       border-color: #0000C0;
//       margin: 0px;
//       padding: 2px;
//       width: auto; 
//       overflow: auto;  
//       font-family: monospace;
//     }
//   </style>
//
//   Also notice that your file will also look reasonable if a browser doesn't 
//   support JavaScript. In such a case, the source code will be presented
//   "as is" inside its <pre> element (the outer <div> element should cause no
//   harm).
//
//   The highlighting style can be controlled with the styles defined below. 
//
//   Volker Simonis, May 2007

explorer = false;
if (document.all) {
  // Explorer case
  explorer = true;
}

// edit lines below to change the output style
comment       = {color:"#0079b9", bold:false, italic:true,  name:"comment"} // comment blocks and lines
precompiler   = {color:"#000099", bold:false, italic:false, name:"pre"} // precompiler lines
operator      = {color:"#805000", bold:false,  italic:false, name:"operator"} // operator and punctuator symbols
stringLiteral = {color:"#008000", bold:false, italic:false, name:"string"} // string and wide char string literals
charLiteral   = {color:"#009900", bold:false, italic:false, name:"char"} // char and wchar_t literals
intLiteral    = {color:"#999900", bold:false, italic:false, name:"int"} // integer literals
floatLiteral  = {color:"#996600", bold:false, italic:false, name:"float"} // floating point literals
boolLiteral   = {color:"#000000", bold:false,  italic:false, name:"bool"} // boolean literals
types         = {color:"#FF6633", bold:false, italic:false, name:"type"} // built-in type names
flowControl   = {color:"#990000", bold:false, italic:false, name:"flow"} // program flow control keywords
keyword       = {color:"#202080", bold:false, italic:false, name:"keyword"} // other keywords

languages = ["CPP", "Java", "ADL"];

keys = new Array(languages.length);
for (var i = 0; i < languages.length; i++) {
  keys[languages[i]] = new Array();
}

//
// C++
//
keys["CPP"].push({style:comment, start:/\s*\/\*[\s\S]*?\*\//mg});
keys["CPP"].push({style:comment, start:/\s*\/\//mg, end:/\n/mg, neglect:/\\|\?\?\//mg});
keys["CPP"].push({style:precompiler, start:/\s*?^\s*(?:#|\?\?=|%:)/mg, end:/\n/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["CPP"].push({style:stringLiteral, start:/\s*(?:\bL)?"/mg, end:/"/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["CPP"].push({style:charLiteral, start:/\s*(?:\bL)?'/mg, end:/'/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["CPP"].push({style:floatLiteral, start:/\s*(?:(?:\b\d+\.\d*|\.\d+)(?:E[\+\-]?\d+)?|\b\d+E[\+\-]?\d+)[FL]?\b|\s*\b\d+\./mgi});
keys["CPP"].push({style:intLiteral, start:/\s*\b(?:0[0-7]*|[1-9]\d*|0x[\dA-F]+)(?:UL?|LU?)?\b/mgi});
keys["CPP"].push({style:boolLiteral, start:/\s*\b(?:true|false)\b/mg});
keys["CPP"].push({style:types, start:/\s*\b(?:bool|char|double|float|int|long|short|signed|unsigned|void|wchar_t)\b/mg});
keys["CPP"].push({style:flowControl, start:/\s*\b(?:break|case|catch|continue|default|do|else|for|goto|if|return|switch|throw|try|while)\b/mg});
keys["CPP"].push({style:keyword, start:/\s*\b(?:asm|auto|class|const_cast|const|delete|dynamic_cast|enum|explicit|export|extern|friend|inline|main|mutable|namespace|new|operator|private|protected|public|register|reinterpret_cast|sizeof|static_cast|static|struct|template|this|typedef|typeid|typename|union|using|virtual|volatile|and_eq|and|bitand|bitor|compl|not_eq|not|or_eq|or|xor_eq|xor)\b/mg});
keys["CPP"].push({style:operator, start:/\s*[\{\}\[\]\(\)<>%:;\.\?\*\+\-\^&\|~!=,\\]+|\s*\//mg});

//
// Java
//
keys["Java"].push({style:comment, start:/\s*\/\*[\s\S]*?\*\//mg});
keys["Java"].push({style:comment, start:/\s*\/\//mg, end:/\n/mg, neglect:/\\|\?\?\//mg});
keys["Java"].push({style:stringLiteral, start:/\s*(?:\bL)?"/mg, end:/"/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
// Basic Java annotation support (VS 2009-02-20)
keys["Java"].push({style:stringLiteral, start:/\s*\@\S+/mg});
keys["Java"].push({style:charLiteral, start:/\s*(?:\bL)?'/mg, end:/'/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["Java"].push({style:floatLiteral, start:/\s*(?:(?:\b\d+\.\d*|\.\d+)(?:E[\+\-]?\d+)?|\b\d+E[\+\-]?\d+)[FL]?\b|\s*\b\d+\./mgi});
keys["Java"].push({style:intLiteral, start:/\s*\b(?:0[0-7]*|[1-9]\d*|0x[\dA-F]+)(?:UL?|LU?)?\b/mgi});
keys["Java"].push({style:boolLiteral, start:/\s*\b(?:true|false|null)\b/mg});
keys["Java"].push({style:types, start:/\s*\b(?:boolean|byte|char|double|float|int|long|short|void)\b/mg});
keys["Java"].push({style:flowControl, start:/\s*\b(?:break|case|catch|continue|default|do|else|for|goto|if|return|switch|synchronized|throw|throws|try|while)\b/mg});
keys["Java"].push({style:keyword, start:/\s*\b(?:abstract|assert|class|const|delete|enum|extends|final|finally|implements|import|instanceof|interface|native|new|package|private|protected|public|static|strictfp|super|this|transient|virtual|volatile)\b/mg});
keys["Java"].push({style:operator, start:/\s*[\{\}\[\]\(\)<>%:;\.\?\*\+\-\^&\|~!=,\\]+|\s*\//mg});

//
// ADL
//
keys["ADL"].push({style:comment, start:/\s*\/\*[\s\S]*?\*\//mg});
keys["ADL"].push({style:comment, start:/\s*\/\//mg, end:/\n/mg, neglect:/\\|\?\?\//mg});
keys["ADL"].push({style:precompiler, start:/\s*?^\s*(?:#|\?\?=|%:)/mg, end:/\n/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["ADL"].push({style:stringLiteral, start:/\s*(?:\bL)?"/mg, end:/"/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["ADL"].push({style:charLiteral, start:/\s*(?:\bL)?'/mg, end:/'/m, neglect:/\\[\s\S]|\?\?\/[\s\S]/m});
keys["ADL"].push({style:floatLiteral, start:/\s*(?:(?:\b\d+\.\d*|\.\d+)(?:E[\+\-]?\d+)?|\b\d+E[\+\-]?\d+)[FL]?\b|\s*\b\d+\./mgi});
keys["ADL"].push({style:intLiteral, start:/\s*\b(?:0[0-7]*|[1-9]\d*|0x[\dA-F]+)(?:UL?|LU?)?\b/mgi});
keys["ADL"].push({style:boolLiteral, start:/\s*\b(?:true|false)\b/mg});
keys["ADL"].push({style:types, start:/\s*\b(?:bool|char|double|float|int|long|short|signed|unsigned|void|wchar_t)\b/mg});
keys["ADL"].push({style:flowControl, start:/\s*\b(?:Set|AbsD|AbsF|AbsI|AddD|AddF|AddI|AddL|AddP|Allocate|AllocateArray|AndI|AndL|AtanD|Binary|Bool|BoxLock|ReverseBytesI|ReverseBytesL|CProj|CallDynamicJava|CallJava|CallLeaf|CallLeafNoFP|CallRuntime|CallStaticJava|CastII|CastX2P|CastP2X|CastPP|Catch|CatchProj|CheckCastPP|ClearArray|ConstraintCast|CMoveD|CMoveF|CMoveI|CMoveL|CMoveP|CmpD|CmpD3|CmpF|CmpF3|CmpI|CmpL|CmpL3|CmpLTMask|CmpP|CmpU|CompareAndSwapI|CompareAndSwapL|CompareAndSwapP|Con|ConD|ConF|ConI|ConL|ConP|Conv2B|ConvD2F|ConvD2I|ConvD2L|ConvF2D|ConvF2I|ConvF2L|ConvI2D|ConvI2F|ConvI2L|ConvL2D|ConvL2F|ConvL2I|CosD|CountedLoop|CountedLoopEnd|CreateEx|DivD|DivF|DivI|DivL|DivMod|DivModI|DivModL|ExpD|FastLock|FastUnlock|Goto|Halt|If|IfFalse|IfTrue|Initialize|JProj|Jump|JumpProj|LShiftI|LShiftL|LoadB|LoadC|LoadD|LoadD_unaligned|LoadF|LoadI|LoadKlass|LoadL|LoadL_unaligned|LoadPLocked|LoadLLocked|LoadP|LoadRange|LoadS|Lock|LogD|Log10D|Loop|Mach|MachProj|MaxI|MemBarAcquire|MemBarCPUOrder|MemBarRelease|MemBarVolatile|MergeMem|MinI|ModD|ModF|ModI|ModL|MoveI2F|MoveF2I|MoveL2D|MoveD2L|MulD|MulF|MulI|MulL|Multi|NegD|NegF|NeverBranch|Opaque1|Opaque2|OrI|OrL|PCTable|Parm|PartialSubtypeCheck|Phi|PowD|PrefetchRead|PrefetchWrite|Proj|RShiftI|RShiftL|Region|Rethrow|Return|Root|RoundDouble|RoundFloat|SafePoint|SCMemProj|SinD|SqrtD|Start|StartOSR|StoreB|StoreC|StoreCM|StorePConditional|StoreLConditional|StoreD|StoreF|StoreI|StoreL|StoreP|StrComp|SubD|SubF|SubI|SubL|TailCall|TailJump|TanD|ThreadLocal|Unlock|URShiftI|URShiftL|XorI|XorL|Vector|AddVB|AddVC|AddVS|AddVI|AddVL|AddVF|AddVD|SubVB|SubVC|SubVS|SubVI|SubVL|SubVF|SubVD|MulVF|MulVD|DivVF|DivVD|LShiftVB|LShiftVC|LShiftVS|LShiftVI|URShiftVB|URShiftVC|URShiftVS|URShiftVI|AndV|OrV|XorV|VectorLoad|Load16B|Load8B|Load4B|Load8C|Load4C|Load2C|Load8S|Load4S|Load2S|Load4I|Load2I|Load2L|Load4F|Load2F|Load2D|VectorStore|Store16B|Store8B|Store4B|Store8C|Store4C|Store2C|Store4I|Store2I|Store2L|Store4F|Store2F|Store2D|Pack|PackB|PackS|PackC|PackI|PackL|PackF|PackD|Pack2x1B|Pack2x2B|Replicate16B|Replicate8B|Replicate4B|Replicate8S|Replicate4S|Replicate2S|Replicate8C|Replicate4C|Replicate2C|Replicate4I|Replicate2I|Replicate2L|Replicate4F|Replicate2F|Replicate2D|Extract|ExtractB|ExtractS|ExtractC|ExtractI|ExtractL|ExtractF|ExtractD|RegI|RegP|RegF|RegD|RegL|RegFlags|Node|break|case|catch|continue|default|do|else|for|goto|if|return|switch|throw|try|while)\b/mg});
keys["ADL"].push({style:keyword, start:/\s*\b(?:instruct|operand|opclass|opcode|source|op_attrib|ins_attrib|match|encode|predicate|constraint|effect|expand|rewrite|format|construct|register|reg_def|reg_class|alloc_class|pipeline|resource|pipe_desc|pipe_class|ins_pipe|ins_cost|ins_encode|size|asm|auto|class|const_cast|const|delete|dynamic_cast|enum|explicit|export|extern|friend|inline|main|mutable|namespace|new|operator|private|protected|public|register|reinterpret_cast|sizeof|static_cast|static|struct|template|this|typedef|typeid|typename|union|using|virtual|volatile|and_eq|and|bitand|bitor|compl|not_eq|not|or_eq|or|xor_eq|xor)\b/mg});
keys["ADL"].push({style:operator, start:/\s*[\{\}\[\]\(\)<>%:;\.\?\*\+\-\^&\|~!=,\\]+|\s*\//mg});

for (var j = 0; j < languages.length; ++j) { 
  language = languages[j];
  for (var i = 0; i < keys[language].length; ++i) { // set xhtml tags
    keys[language][i].before = "<span class=\"highlight_" + language + "_" + keys[language][i].style.name + "\">";
    keys[language][i].after = "</span>";
  }
}

document.writeln("<style type='text/css' id='highliteStyle'>");
for (var j = 0; j < languages.length; ++j) { 
  language = languages[j];
  for (var i = 1; i != keys[language].length; ++i) {
    document.write(".highlight_" + language + "_" + keys[language][i].style.name + 
                   " { color: " + keys[language][i].style.color + "; ");
    if (keys[language][i].style.bold) document.write("font-weight: bold; ");
    if (keys[language][i].style.italic) document.write("font-style: italic; ");
    document.write("font-family: monospace; ");
    document.writeln("}\n");
  }
}
document.writeln("</style>");

// Check if the element "elem" has a "class" attribute that contains
// "listing" as value. If yes, return the language or "CPP" by default.
function isListing(divElem) {
  var classAttrib = 0;
  // Explorer version
  if (explorer) {
    for(var i = 0; i < divElem.attributes.length; i++ ) {
      if(divElem.attributes[i].nodeName.toLowerCase() == "class" &&
         divElem.attributes[i].nodeValue.indexOf("listing") != -1) {
        classAttrib = divElem.attributes[i].nodeValue;
      }
    }
  }
  // DOM version
  else {
    if (divElem.hasAttribute("class") &&
        divElem.getAttribute("class").indexOf("listing") != -1) {
      classAttrib = divElem.getAttribute("class");
    }
  }
  if (classAttrib != 0) {
    for (var j = 0; j < languages.length; ++j) { 
      var language = languages[j];
      if (classAttrib.toLowerCase().indexOf(language.toLowerCase()) != -1) {
        return language;
      }
    }
    return "CPP";
  }
  return 0;
}

function getText(divElem) {
  var rawListing;
  // Explorer version
  if (explorer) {
    rawListing = divElem.innerHTML;
  }
  // DOM version
  else {
    //return divElem.textContent; // Doesn't work because it kills whitespace
    rawListing = divElem.innerHTML;
  }
  return rawListing;
}

function replaceText(divElem, fancyListing) {
  // Explorer version
  if (explorer) {
    divElem.innerHTML = fancyListing;
  }
  // DOM version
  else {
    divElem.innerHTML = fancyListing;
  }
}

function toHTML(s) { // convert special chars
  s = s.split("&").join("&amp;");
  s = s.split("<").join("&lt;");
  return s.split(">").join("&gt;");
}

function highlight(rawListing, language) {
  // For Gecko engines (Firefox, Mozilla) 'innerHTML' only respects
  // the formatting (whitespace and linebreaks) inside a <pre> element.
  // That's why we have to use a <pre> block inside the listings <div>
  // block. Here we cut the <pre> tag so we don't confuse the highlighter.
  var fancyListing = "<pre class='listing'>";
  var tmp;
  if (tmp = rawListing.match(/^<pre[^>]*>/mgi)) {
    fancyListing = tmp[0];
  }
  rawListing = rawListing.replace(/^<pre[^>]*>\n?/mgi, "");
  rawListing = rawListing.replace(/\r?\n?<\/pre>$/mgi, "");
  // If the listing we process has been preprocessed by some XML-tools
  // it may have been replaced '<', '>' and '&' with '&lt;', '&gt;' and '&amp;'
  // respectively, so we undo this changes!
  rawListing = rawListing.replace(/&amp;/mgi, "&");
  rawListing = rawListing.replace(/&lt;/mgi, "<");
  rawListing = rawListing.replace(/&gt;/mgi, ">");

  var s = rawListing.replace(/\r\n?/gm, "\n"); // convert DOS and/or MAC to UNIX
  var keyString = "";
  var match = 0;
  
  var previousMatch = -1;
  for (var i = 0; i != keys[language].length; ++i) {
    keys[language][i].startPos = -1;
  }
  for (var position = 0; position != s.length; position = keys[language][match].endPos) {
    for (var i = 0; i != keys[language].length; ++i) {
      if (keys[language][i].startPos < position) { // update needed
        keys[language][i].start.lastIndex = position;
        var result = keys[language][i].start.exec(s);
        if (result != null) {
          keys[language][i].startPos = result.index;
          keys[language][i].endPos = keys[language][i].start.lastIndex;
        }
        else {
          keys[language][i].startPos = keys[language][i].endPos = s.length;
        }
      }
    }
    match = 0;
    for (var i = 1; i < keys[language].length; ++i) { // find first matching key
      if (keys[language][i].startPos < keys[language][match].startPos) {
        match = i;
      }
    }
    if (keys[language][match].end != undefined) { // end must be found
      var end = new RegExp(keys[language][match].end.source + "|" + keys[language][match].neglect.source, "mg");
      end.lastIndex = keys[language][match].endPos;
      while (keys[language][match].endPos != s.length) {
        result = end.exec(s);
        if (result != null) {
          if (result[0].search(keys[language][match].end) == 0) {
            keys[language][match].endPos = end.lastIndex;
            break;
          }
        }
        else {
          keys[language][match].endPos = s.length;
        }
      }
    }
    var before = s.substring(position, keys[language][match].startPos);
    keyString = s.substring(keys[language][match].startPos, keys[language][match].endPos);
    var output = "";
    if ((before == "") && (match == previousMatch)) {
      output += toHTML(keyString);
    }
    else {
      if (previousMatch != -1) {
        output += keys[language][previousMatch].after;
      } 
      output += toHTML(before);
      if (keyString != "") {
        output += keys[language][match].before + toHTML(keyString);
      }
    }
    previousMatch = match;
    fancyListing += output;
  }
  if (keyString != "") {
    fancyListing += keys[language][match].after;
  }
  return fancyListing + "</pre>";
}

function highlighter() {
  // Get all the <div> elements..
  var listings = document.getElementsByTagName("div");
  for (var i = 0; i < listings.length; i++) {
    var listing = listings[i];
    // .. that have a "listing" class attribute.
    var language;
    if (language = isListing(listing)) {
      // Get the source code from the <div> element..
      var rawListing = getText(listing);
      // .. highlite it ..
      var fancyListing = highlight(rawListing, language);
      // .. and replace the raw source code with the highligted one.
      replaceText(listing, fancyListing);
    }
  }
}

// Now bind the highlighter method to the 'onload' event such that 
// it'll get a chance to process the DOM once the HTML document was loaded.
if (window.addEventListener) //DOM method for binding an event
  window.addEventListener("load", highlighter, false)
else if (window.attachEvent) //IE exclusive method for binding an event
  window.attachEvent("onload", highlighter)
else if (document.getElementById) //support older modern browsers
  window.onload=highlighter
