href = (start + 1); href.StripWhitespace();
HTMLContentSink::ProcessLink(nsIHTMLContent* aElement, const nsString& aLinkData){  nsresult result = NS_OK;    // parse link content and call process style link  nsAutoString href;  nsAutoString rel;  nsAutoString title;  nsAutoString type;  nsAutoString media;  PRBool blockParser = PR_FALSE;  PRBool didBlock;  nsAutoString  stringList(aLinkData); // copy to work buffer    stringList.Append(kNullCh);  // put an extra null at the end  PRUnichar* start = (PRUnichar*)stringList;  PRUnichar* end   = start;  PRUnichar* last  = start;  while (kNullCh != *start) {    while ((kNullCh != *start) && nsString::IsSpace(*start)) {  // skip leading space      start++;    }    end = start;    last = end - 1;    while ((kNullCh != *end) && (kSemiCh != *end)) { // look for semicolon      if ((kApostrophe == *end) || (kQuote == *end) ||           (kLessThanCh == *end)) { // quoted string        PRUnichar quote = *end;        if (kLessThanCh == quote) {          quote = kGreaterThanCh;        }        PRUnichar* closeQuote = (end + 1);        while ((kNullCh != *closeQuote) && (quote != *closeQuote)) {          closeQuote++; // seek closing quote        }        if (quote == *closeQuote) { // found closer          end = closeQuote; // skip to close quote          last = end - 1;          if ((kSemiCh != *(end + 1)) && (kNullCh != *(end + 1))) {            *(++end) = kNullCh;     // end string here            while ((kNullCh != *(end + 1)) && (kSemiCh != *(end + 1))) { // keep going until semi              end++;            }          }        }      }      end++;      last++;    }    *end = kNullCh; // end string here    if (start < end) {      if ((kLessThanCh == *start) && (kGreaterThanCh == *last)) {        *last = kNullCh;        if (0 < href.Length()) {  // this is not the first href, process what we have and reset          result = ProcessStyleLink(aElement, href, rel, title, type, media, blockParser);          rel.Truncate();          title.Truncate();          type.Truncate();          media.Truncate();          if (blockParser) {            blockParser = PR_FALSE;            didBlock = PR_TRUE;          }        }        href = (start + 1);        href.StripWhitespace();      }      else {        PRUnichar* equals = start;        while ((kNullCh != *equals) && (kEqualsCh != *equals)) {          equals++;        }        if (kNullCh != *equals) {          *equals = kNullCh;          nsAutoString  attr = start;          attr.StripWhitespace();          PRUnichar* value = ++equals;          while (nsString::IsSpace(*value)) {            value++;          }          if (((kApostrophe == *value) || (kQuote == *value)) &&              (*value == *last)) {            *last = kNullCh;            value++;          }          if (attr.EqualsIgnoreCase("rel")) {            rel = value;            rel.CompressWhitespace();          }          else if (attr.EqualsIgnoreCase("title")) {            title = value;            title.CompressWhitespace();          }          else if (attr.EqualsIgnoreCase("type")) {            type = value;            type.StripWhitespace();          }          else if (attr.EqualsIgnoreCase("media")) {            media = value;          }          else if (attr.EqualsIgnoreCase("wait")) {            blockParser = PR_TRUE;          }        }      }    }    start = ++end;  }  if (0 < href.Length()) {    result = ProcessStyleLink(aElement, href, rel, title, type, media, blockParser);    if (NS_SUCCEEDED(result) && (blockParser || didBlock)) {      result = NS_ERROR_HTMLPARSER_BLOCK;    }  }  return result;}