aabbaabb updated this revision to Diff 345329. aabbaabb added a comment. put libs in 'lib' folder, 'analyze-*' and 'scan-*' compiler wrappers to 'libexec', also copy the resources in 'libscanbuild'
Tests: To install: DESTDIR=${INSTALL_DIR} ninja install-scan-build-py -j1000 Test at source folder: PATH=~/llvm-project/build/libexec:~/llvm-project/build/bin:$PATH python -m unittest tests.unit PATH=~/llvm-project/build/libexec:~/llvm-project/build/bin:$PATH python -m unittest tests.functional.cases One error in functional test: test_successful_build_on_empty_env I think this is intended behavior (clang not found?) since the test sets an empty environment for make. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101139/new/ https://reviews.llvm.org/D101139 Files: clang/cmake/caches/Fuchsia-stage2.cmake clang/tools/CMakeLists.txt clang/tools/scan-build-py/CMakeLists.txt clang/tools/scan-build-py/bin/analyze-build clang/tools/scan-build-py/bin/analyze-c++ clang/tools/scan-build-py/bin/analyze-cc clang/tools/scan-build-py/bin/intercept-build clang/tools/scan-build-py/bin/intercept-c++ clang/tools/scan-build-py/bin/intercept-cc clang/tools/scan-build-py/bin/scan-build clang/tools/scan-build-py/lib/libear/__init__.py clang/tools/scan-build-py/lib/libear/config.h.in clang/tools/scan-build-py/lib/libear/ear.c clang/tools/scan-build-py/lib/libscanbuild/__init__.py clang/tools/scan-build-py/lib/libscanbuild/analyze.py clang/tools/scan-build-py/lib/libscanbuild/arguments.py clang/tools/scan-build-py/lib/libscanbuild/clang.py clang/tools/scan-build-py/lib/libscanbuild/compilation.py clang/tools/scan-build-py/lib/libscanbuild/intercept.py clang/tools/scan-build-py/lib/libscanbuild/report.py clang/tools/scan-build-py/lib/libscanbuild/resources/scanview.css clang/tools/scan-build-py/lib/libscanbuild/resources/selectable.js clang/tools/scan-build-py/lib/libscanbuild/resources/sorttable.js clang/tools/scan-build-py/lib/libscanbuild/shell.py clang/tools/scan-build-py/libear/__init__.py clang/tools/scan-build-py/libear/config.h.in clang/tools/scan-build-py/libear/ear.c clang/tools/scan-build-py/libexec/analyze-c++ clang/tools/scan-build-py/libexec/analyze-cc clang/tools/scan-build-py/libexec/intercept-c++ clang/tools/scan-build-py/libexec/intercept-cc clang/tools/scan-build-py/libscanbuild/__init__.py clang/tools/scan-build-py/libscanbuild/analyze.py clang/tools/scan-build-py/libscanbuild/arguments.py clang/tools/scan-build-py/libscanbuild/clang.py clang/tools/scan-build-py/libscanbuild/compilation.py clang/tools/scan-build-py/libscanbuild/intercept.py clang/tools/scan-build-py/libscanbuild/report.py clang/tools/scan-build-py/libscanbuild/resources/scanview.css clang/tools/scan-build-py/libscanbuild/resources/selectable.js clang/tools/scan-build-py/libscanbuild/resources/sorttable.js clang/tools/scan-build-py/libscanbuild/shell.py clang/tools/scan-build-py/tests/__init__.py clang/tools/scan-build-py/tests/functional/cases/__init__.py clang/tools/scan-build-py/tests/functional/cases/test_exec_anatomy.py clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py clang/tools/scan-build-py/tests/unit/test_analyze.py
Index: clang/tools/scan-build-py/tests/unit/test_analyze.py =================================================================== --- clang/tools/scan-build-py/tests/unit/test_analyze.py +++ clang/tools/scan-build-py/tests/unit/test_analyze.py @@ -18,9 +18,9 @@ # scan-build can be easily matched up to compare results. def test_directory_name_comparison(self): with libear.TemporaryDirectory() as tmpdir, \ - sut.report_directory(tmpdir, False) as report_dir1, \ - sut.report_directory(tmpdir, False) as report_dir2, \ - sut.report_directory(tmpdir, False) as report_dir3: + sut.report_directory(tmpdir, False, 'html') as report_dir1, \ + sut.report_directory(tmpdir, False, 'html') as report_dir2, \ + sut.report_directory(tmpdir, False, 'html') as report_dir3: self.assertLess(report_dir1, report_dir2) self.assertLess(report_dir2, report_dir3) Index: clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py =================================================================== --- clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py +++ clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py @@ -15,7 +15,7 @@ def prepare_cdb(name, target_dir): target_file = 'build_{0}.json'.format(name) this_dir, _ = os.path.split(__file__) - path = os.path.normpath(os.path.join(this_dir, '..', 'src')) + path = os.path.abspath(os.path.join(this_dir, '..', 'src')) source_dir = os.path.join(path, 'compilation_database') source_file = os.path.join(source_dir, target_file + '.in') target_file = os.path.join(target_dir, 'compile_commands.json') Index: clang/tools/scan-build-py/tests/functional/cases/test_exec_anatomy.py =================================================================== --- clang/tools/scan-build-py/tests/functional/cases/test_exec_anatomy.py +++ clang/tools/scan-build-py/tests/functional/cases/test_exec_anatomy.py @@ -43,7 +43,7 @@ def test_all_exec_calls(self): this_dir, _ = os.path.split(__file__) - source_dir = os.path.normpath(os.path.join(this_dir, '..', 'exec')) + source_dir = os.path.abspath(os.path.join(this_dir, '..', 'exec')) with libear.TemporaryDirectory() as tmp_dir: expected, result = run(source_dir, tmp_dir) self.assertEqualJson(expected, result) Index: clang/tools/scan-build-py/tests/functional/cases/__init__.py =================================================================== --- clang/tools/scan-build-py/tests/functional/cases/__init__.py +++ clang/tools/scan-build-py/tests/functional/cases/__init__.py @@ -22,7 +22,7 @@ def make_args(target): this_dir, _ = os.path.split(__file__) - path = os.path.normpath(os.path.join(this_dir, '..', 'src')) + path = os.path.abspath(os.path.join(this_dir, '..', 'src')) return ['make', 'SRCDIR={}'.format(path), 'OBJDIR={}'.format(target), '-f', os.path.join(path, 'build', 'Makefile')] Index: clang/tools/scan-build-py/tests/__init__.py =================================================================== --- clang/tools/scan-build-py/tests/__init__.py +++ clang/tools/scan-build-py/tests/__init__.py @@ -3,6 +3,12 @@ # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +import os +import sys + +this_dir = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) + import unittest import tests.unit Index: clang/tools/scan-build-py/libscanbuild/resources/sorttable.js =================================================================== --- clang/tools/scan-build-py/libscanbuild/resources/sorttable.js +++ /dev/null @@ -1,492 +0,0 @@ -/* - SortTable - version 2 - 7th April 2007 - Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ - - Instructions: - Download this file - Add <script src="sorttable.js"></script> to your HTML - Add class="sortable" to any table you'd like to make sortable - Click on the headers to sort - - Thanks to many, many people for contributions and suggestions. - Licenced as X11: http://www.kryogenix.org/code/browser/licence.html - This basically means: do what you want with it. -*/ - - -var stIsIE = /*@cc_on!@*/false; - -sorttable = { - init: function() { - // quit if this function has already been called - if (arguments.callee.done) return; - // flag this function so we don't do the same thing twice - arguments.callee.done = true; - // kill the timer - if (_timer) clearInterval(_timer); - - if (!document.createElement || !document.getElementsByTagName) return; - - sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; - - forEach(document.getElementsByTagName('table'), function(table) { - if (table.className.search(/\bsortable\b/) != -1) { - sorttable.makeSortable(table); - } - }); - - }, - - makeSortable: function(table) { - if (table.getElementsByTagName('thead').length == 0) { - // table doesn't have a tHead. Since it should have, create one and - // put the first table row in it. - the = document.createElement('thead'); - the.appendChild(table.rows[0]); - table.insertBefore(the,table.firstChild); - } - // Safari doesn't support table.tHead, sigh - if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; - - if (table.tHead.rows.length != 1) return; // can't cope with two header rows - - // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as - // "total" rows, for example). This is B&R, since what you're supposed - // to do is put them in a tfoot. So, if there are sortbottom rows, - // for backward compatibility, move them to tfoot (creating it if needed). - sortbottomrows = []; - for (var i=0; i<table.rows.length; i++) { - if (table.rows[i].className.search(/\bsortbottom\b/) != -1) { - sortbottomrows[sortbottomrows.length] = table.rows[i]; - } - } - if (sortbottomrows) { - if (table.tFoot == null) { - // table doesn't have a tfoot. Create one. - tfo = document.createElement('tfoot'); - table.appendChild(tfo); - } - for (var i=0; i<sortbottomrows.length; i++) { - tfo.appendChild(sortbottomrows[i]); - } - delete sortbottomrows; - } - - // work through each column and calculate its type - headrow = table.tHead.rows[0].cells; - for (var i=0; i<headrow.length; i++) { - // manually override the type with a sorttable_type attribute - if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col - mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/); - if (mtch) { override = mtch[1]; } - if (mtch && typeof sorttable["sort_"+override] == 'function') { - headrow[i].sorttable_sortfunction = sorttable["sort_"+override]; - } else { - headrow[i].sorttable_sortfunction = sorttable.guessType(table,i); - } - // make it clickable to sort - headrow[i].sorttable_columnindex = i; - headrow[i].sorttable_tbody = table.tBodies[0]; - dean_addEvent(headrow[i],"click", function(e) { - - if (this.className.search(/\bsorttable_sorted\b/) != -1) { - // if we're already sorted by this column, just - // reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted', - 'sorttable_sorted_reverse'); - this.removeChild(document.getElementById('sorttable_sortfwdind')); - sortrevind = document.createElement('span'); - sortrevind.id = "sorttable_sortrevind"; - sortrevind.innerHTML = stIsIE ? ' <font face="webdings">5</font>' : ' ▴'; - this.appendChild(sortrevind); - return; - } - if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { - // if we're already sorted by this column in reverse, just - // re-reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted_reverse', - 'sorttable_sorted'); - this.removeChild(document.getElementById('sorttable_sortrevind')); - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; - this.appendChild(sortfwdind); - return; - } - - // remove sorttable_sorted classes - theadrow = this.parentNode; - forEach(theadrow.childNodes, function(cell) { - if (cell.nodeType == 1) { // an element - cell.className = cell.className.replace('sorttable_sorted_reverse',''); - cell.className = cell.className.replace('sorttable_sorted',''); - } - }); - sortfwdind = document.getElementById('sorttable_sortfwdind'); - if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } - sortrevind = document.getElementById('sorttable_sortrevind'); - if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } - - this.className += ' sorttable_sorted'; - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; - this.appendChild(sortfwdind); - - // build an array to sort. This is a Schwartzian transform thing, - // i.e., we "decorate" each row with the actual sort key, - // sort based on the sort keys, and then put the rows back in order - // which is a lot faster because you only do getInnerText once per row - row_array = []; - col = this.sorttable_columnindex; - rows = this.sorttable_tbody.rows; - for (var j=0; j<rows.length; j++) { - row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]]; - } - /* If you want a stable sort, uncomment the following line */ - sorttable.shaker_sort(row_array, this.sorttable_sortfunction); - /* and comment out this one */ - //row_array.sort(this.sorttable_sortfunction); - - tb = this.sorttable_tbody; - for (var j=0; j<row_array.length; j++) { - tb.appendChild(row_array[j][1]); - } - - delete row_array; - }); - } - } - }, - - guessType: function(table, column) { - // guess the type of a column based on its first non-blank row - sortfn = sorttable.sort_alpha; - for (var i=0; i<table.tBodies[0].rows.length; i++) { - text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]); - if (text != '') { - if (text.match(/^-?[ï½£$、]?[\d,.]+%?$/)) { - return sorttable.sort_numeric; - } - // check for a date: dd/mm/yyyy or dd/mm/yy - // can have / or . or - as separator - // can be mm/dd as well - possdate = text.match(sorttable.DATE_RE) - if (possdate) { - // looks like a date - first = parseInt(possdate[1]); - second = parseInt(possdate[2]); - if (first > 12) { - // definitely dd/mm - return sorttable.sort_ddmm; - } else if (second > 12) { - return sorttable.sort_mmdd; - } else { - // looks like a date, but we can't tell which, so assume - // that it's dd/mm (English imperialism!) and keep looking - sortfn = sorttable.sort_ddmm; - } - } - } - } - return sortfn; - }, - - getInnerText: function(node) { - // gets the text we want to use for sorting for a cell. - // strips leading and trailing whitespace. - // this is *not* a generic getInnerText function; it's special to sorttable. - // for example, you can override the cell text with a customkey attribute. - // it also gets .value for <input> fields. - - hasInputs = (typeof node.getElementsByTagName == 'function') && - node.getElementsByTagName('input').length; - - if (node.getAttribute("sorttable_customkey") != null) { - return node.getAttribute("sorttable_customkey"); - } - else if (typeof node.textContent != 'undefined' && !hasInputs) { - return node.textContent.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.innerText != 'undefined' && !hasInputs) { - return node.innerText.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.text != 'undefined' && !hasInputs) { - return node.text.replace(/^\s+|\s+$/g, ''); - } - else { - switch (node.nodeType) { - case 3: - if (node.nodeName.toLowerCase() == 'input') { - return node.value.replace(/^\s+|\s+$/g, ''); - } - case 4: - return node.nodeValue.replace(/^\s+|\s+$/g, ''); - break; - case 1: - case 11: - var innerText = ''; - for (var i = 0; i < node.childNodes.length; i++) { - innerText += sorttable.getInnerText(node.childNodes[i]); - } - return innerText.replace(/^\s+|\s+$/g, ''); - break; - default: - return ''; - } - } - }, - - reverse: function(tbody) { - // reverse the rows in a tbody - newrows = []; - for (var i=0; i<tbody.rows.length; i++) { - newrows[newrows.length] = tbody.rows[i]; - } - for (var i=newrows.length-1; i>=0; i--) { - tbody.appendChild(newrows[i]); - } - delete newrows; - }, - - /* sort functions - each sort function takes two parameters, a and b - you are comparing a[0] and b[0] */ - sort_numeric: function(a,b) { - aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); - if (isNaN(aa)) aa = 0; - bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); - if (isNaN(bb)) bb = 0; - return aa-bb; - }, - sort_alpha: function(a,b) { - if (a[0]==b[0]) return 0; - if (a[0]<b[0]) return -1; - return 1; - }, - sort_ddmm: function(a,b) { - mtch = a[0].match(sorttable.DATE_RE); - y = mtch[3]; m = mtch[2]; d = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt1 = y+m+d; - mtch = b[0].match(sorttable.DATE_RE); - y = mtch[3]; m = mtch[2]; d = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt2 = y+m+d; - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; - }, - sort_mmdd: function(a,b) { - mtch = a[0].match(sorttable.DATE_RE); - y = mtch[3]; d = mtch[2]; m = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt1 = y+m+d; - mtch = b[0].match(sorttable.DATE_RE); - y = mtch[3]; d = mtch[2]; m = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt2 = y+m+d; - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; - }, - - shaker_sort: function(list, comp_func) { - // A stable sort function to allow multi-level sorting of data - // see: http://en.wikipedia.org/wiki/Cocktail_sort - // thanks to Joseph Nahmias - var b = 0; - var t = list.length - 1; - var swap = true; - - while(swap) { - swap = false; - for(var i = b; i < t; ++i) { - if ( comp_func(list[i], list[i+1]) > 0 ) { - var q = list[i]; list[i] = list[i+1]; list[i+1] = q; - swap = true; - } - } // for - t--; - - if (!swap) break; - - for(var i = t; i > b; --i) { - if ( comp_func(list[i], list[i-1]) < 0 ) { - var q = list[i]; list[i] = list[i-1]; list[i-1] = q; - swap = true; - } - } // for - b++; - - } // while(swap) - } -} - -/* ****************************************************************** - Supporting functions: bundled here to avoid depending on a library - ****************************************************************** */ - -// Dean Edwards/Matthias Miller/John Resig - -/* for Mozilla/Opera9 */ -if (document.addEventListener) { - document.addEventListener("DOMContentLoaded", sorttable.init, false); -} - -/* for Internet Explorer */ -/*@cc_on @*/ -/*@if (@_win32) - document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>"); - var script = document.getElementById("__ie_onload"); - script.onreadystatechange = function() { - if (this.readyState == "complete") { - sorttable.init(); // call the onload handler - } - }; -/*@end @*/ - -/* for Safari */ -if (/WebKit/i.test(navigator.userAgent)) { // sniff - var _timer = setInterval(function() { - if (/loaded|complete/.test(document.readyState)) { - sorttable.init(); // call the onload handler - } - }, 10); -} - -/* for other browsers */ -window.onload = sorttable.init; - -// written by Dean Edwards, 2005 -// with input from Tino Zijdel, Matthias Miller, Diego Perini - -// http://dean.edwards.name/weblog/2005/10/add-event/ - -function dean_addEvent(element, type, handler) { - if (element.addEventListener) { - element.addEventListener(type, handler, false); - } else { - // assign each event handler a unique ID - if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++; - // create a hash table of event types for the element - if (!element.events) element.events = {}; - // create a hash table of event handlers for each element/event pair - var handlers = element.events[type]; - if (!handlers) { - handlers = element.events[type] = {}; - // store the existing event handler (if there is one) - if (element["on" + type]) { - handlers[0] = element["on" + type]; - } - } - // store the event handler in the hash table - handlers[handler.$$guid] = handler; - // assign a global event handler to do all the work - element["on" + type] = handleEvent; - } -}; -// a counter used to create unique IDs -dean_addEvent.guid = 1; - -function removeEvent(element, type, handler) { - if (element.removeEventListener) { - element.removeEventListener(type, handler, false); - } else { - // delete the event handler from the hash table - if (element.events && element.events[type]) { - delete element.events[type][handler.$$guid]; - } - } -}; - -function handleEvent(event) { - var returnValue = true; - // grab the event object (IE uses a global event object) - event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); - // get a reference to the hash table of event handlers - var handlers = this.events[event.type]; - // execute each event handler - for (var i in handlers) { - this.$$handleEvent = handlers[i]; - if (this.$$handleEvent(event) === false) { - returnValue = false; - } - } - return returnValue; -}; - -function fixEvent(event) { - // add W3C standard event methods - event.preventDefault = fixEvent.preventDefault; - event.stopPropagation = fixEvent.stopPropagation; - return event; -}; -fixEvent.preventDefault = function() { - this.returnValue = false; -}; -fixEvent.stopPropagation = function() { - this.cancelBubble = true; -} - -// Dean's forEach: http://dean.edwards.name/base/forEach.js -/* - forEach, version 1.0 - Copyright 2006, Dean Edwards - License: http://www.opensource.org/licenses/mit-license.php -*/ - -// array-like enumeration -if (!Array.forEach) { // mozilla already supports this - Array.forEach = function(array, block, context) { - for (var i = 0; i < array.length; i++) { - block.call(context, array[i], i, array); - } - }; -} - -// generic enumeration -Function.prototype.forEach = function(object, block, context) { - for (var key in object) { - if (typeof this.prototype[key] == "undefined") { - block.call(context, object[key], key, object); - } - } -}; - -// character enumeration -String.forEach = function(string, block, context) { - Array.forEach(string.split(""), function(chr, index) { - block.call(context, chr, index, string); - }); -}; - -// globally resolve forEach enumeration -var forEach = function(object, block, context) { - if (object) { - var resolve = Object; // default - if (object instanceof Function) { - // functions have a "length" property - resolve = Function; - } else if (object.forEach instanceof Function) { - // the object implements a custom forEach method so use that - object.forEach(block, context); - return; - } else if (typeof object == "string") { - // the object is a string - resolve = String; - } else if (typeof object.length == "number") { - // the object is array-like - resolve = Array; - } - resolve.forEach(object, block, context); - } -}; Index: clang/tools/scan-build-py/libexec/intercept-cc =================================================================== --- clang/tools/scan-build-py/libexec/intercept-cc +++ clang/tools/scan-build-py/libexec/intercept-cc @@ -7,7 +7,7 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) from libscanbuild.intercept import intercept_compiler_wrapper sys.exit(intercept_compiler_wrapper()) Index: clang/tools/scan-build-py/libexec/intercept-c++ =================================================================== --- clang/tools/scan-build-py/libexec/intercept-c++ +++ clang/tools/scan-build-py/libexec/intercept-c++ @@ -7,7 +7,7 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) from libscanbuild.intercept import intercept_compiler_wrapper sys.exit(intercept_compiler_wrapper()) Index: clang/tools/scan-build-py/libexec/analyze-cc =================================================================== --- clang/tools/scan-build-py/libexec/analyze-cc +++ clang/tools/scan-build-py/libexec/analyze-cc @@ -7,7 +7,7 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) from libscanbuild.analyze import analyze_compiler_wrapper sys.exit(analyze_compiler_wrapper()) Index: clang/tools/scan-build-py/libexec/analyze-c++ =================================================================== --- clang/tools/scan-build-py/libexec/analyze-c++ +++ clang/tools/scan-build-py/libexec/analyze-c++ @@ -7,7 +7,8 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) + from libscanbuild.analyze import analyze_compiler_wrapper sys.exit(analyze_compiler_wrapper()) Index: clang/tools/scan-build-py/libear/ear.c =================================================================== --- clang/tools/scan-build-py/libear/ear.c +++ /dev/null @@ -1,604 +0,0 @@ -/* -*- coding: utf-8 -*- -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -*/ - -/** - * This file implements a shared library. This library can be pre-loaded by - * the dynamic linker of the Operating System (OS). It implements a few function - * related to process creation. By pre-load this library the executed process - * uses these functions instead of those from the standard library. - * - * The idea here is to inject a logic before call the real methods. The logic is - * to dump the call into a file. To call the real method this library is doing - * the job of the dynamic linker. - * - * The only input for the log writing is about the destination directory. - * This is passed as environment variable. - */ - -#include "config.h" - -#include <stddef.h> -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <dlfcn.h> -#include <pthread.h> - -#if defined HAVE_POSIX_SPAWN || defined HAVE_POSIX_SPAWNP -#include <spawn.h> -#endif - -#if defined HAVE_NSGETENVIRON -# include <crt_externs.h> -#else -extern char **environ; -#endif - -#define ENV_OUTPUT "INTERCEPT_BUILD_TARGET_DIR" -#ifdef APPLE -# define ENV_FLAT "DYLD_FORCE_FLAT_NAMESPACE" -# define ENV_PRELOAD "DYLD_INSERT_LIBRARIES" -# define ENV_SIZE 3 -#else -# define ENV_PRELOAD "LD_PRELOAD" -# define ENV_SIZE 2 -#endif - -#define DLSYM(TYPE_, VAR_, SYMBOL_) \ - union { \ - void *from; \ - TYPE_ to; \ - } cast; \ - if (0 == (cast.from = dlsym(RTLD_NEXT, SYMBOL_))) { \ - perror("bear: dlsym"); \ - exit(EXIT_FAILURE); \ - } \ - TYPE_ const VAR_ = cast.to; - - -typedef char const * bear_env_t[ENV_SIZE]; - -static int bear_capture_env_t(bear_env_t *env); -static int bear_reset_env_t(bear_env_t *env); -static void bear_release_env_t(bear_env_t *env); -static char const **bear_update_environment(char *const envp[], bear_env_t *env); -static char const **bear_update_environ(char const **in, char const *key, char const *value); -static char **bear_get_environment(); -static void bear_report_call(char const *fun, char const *const argv[]); -static char const **bear_strings_build(char const *arg, va_list *ap); -static char const **bear_strings_copy(char const **const in); -static char const **bear_strings_append(char const **in, char const *e); -static size_t bear_strings_length(char const *const *in); -static void bear_strings_release(char const **); - - -static bear_env_t env_names = - { ENV_OUTPUT - , ENV_PRELOAD -#ifdef ENV_FLAT - , ENV_FLAT -#endif - }; - -static bear_env_t initial_env = - { 0 - , 0 -#ifdef ENV_FLAT - , 0 -#endif - }; - -static int initialized = 0; -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -static void on_load(void) __attribute__((constructor)); -static void on_unload(void) __attribute__((destructor)); - - -#ifdef HAVE_EXECVE -static int call_execve(const char *path, char *const argv[], - char *const envp[]); -#endif -#ifdef HAVE_EXECVP -static int call_execvp(const char *file, char *const argv[]); -#endif -#ifdef HAVE_EXECVPE -static int call_execvpe(const char *file, char *const argv[], - char *const envp[]); -#endif -#ifdef HAVE_EXECVP2 -static int call_execvP(const char *file, const char *search_path, - char *const argv[]); -#endif -#ifdef HAVE_EXECT -static int call_exect(const char *path, char *const argv[], - char *const envp[]); -#endif -#ifdef HAVE_POSIX_SPAWN -static int call_posix_spawn(pid_t *restrict pid, const char *restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], - char *const envp[restrict]); -#endif -#ifdef HAVE_POSIX_SPAWNP -static int call_posix_spawnp(pid_t *restrict pid, const char *restrict file, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], - char *const envp[restrict]); -#endif - - -/* Initialization method to Captures the relevant environment variables. - */ - -static void on_load(void) { - pthread_mutex_lock(&mutex); - if (!initialized) - initialized = bear_capture_env_t(&initial_env); - pthread_mutex_unlock(&mutex); -} - -static void on_unload(void) { - pthread_mutex_lock(&mutex); - bear_release_env_t(&initial_env); - initialized = 0; - pthread_mutex_unlock(&mutex); -} - - -/* These are the methods we are try to hijack. - */ - -#ifdef HAVE_EXECVE -int execve(const char *path, char *const argv[], char *const envp[]) { - bear_report_call(__func__, (char const *const *)argv); - return call_execve(path, argv, envp); -} -#endif - -#ifdef HAVE_EXECV -#ifndef HAVE_EXECVE -#error can not implement execv without execve -#endif -int execv(const char *path, char *const argv[]) { - bear_report_call(__func__, (char const *const *)argv); - char * const * envp = bear_get_environment(); - return call_execve(path, argv, envp); -} -#endif - -#ifdef HAVE_EXECVPE -int execvpe(const char *file, char *const argv[], char *const envp[]) { - bear_report_call(__func__, (char const *const *)argv); - return call_execvpe(file, argv, envp); -} -#endif - -#ifdef HAVE_EXECVP -int execvp(const char *file, char *const argv[]) { - bear_report_call(__func__, (char const *const *)argv); - return call_execvp(file, argv); -} -#endif - -#ifdef HAVE_EXECVP2 -int execvP(const char *file, const char *search_path, char *const argv[]) { - bear_report_call(__func__, (char const *const *)argv); - return call_execvP(file, search_path, argv); -} -#endif - -#ifdef HAVE_EXECT -int exect(const char *path, char *const argv[], char *const envp[]) { - bear_report_call(__func__, (char const *const *)argv); - return call_exect(path, argv, envp); -} -#endif - -#ifdef HAVE_EXECL -# ifndef HAVE_EXECVE -# error can not implement execl without execve -# endif -int execl(const char *path, const char *arg, ...) { - va_list args; - va_start(args, arg); - char const **argv = bear_strings_build(arg, &args); - va_end(args); - - bear_report_call(__func__, (char const *const *)argv); - char * const * envp = bear_get_environment(); - int const result = call_execve(path, (char *const *)argv, envp); - - bear_strings_release(argv); - return result; -} -#endif - -#ifdef HAVE_EXECLP -# ifndef HAVE_EXECVP -# error can not implement execlp without execvp -# endif -int execlp(const char *file, const char *arg, ...) { - va_list args; - va_start(args, arg); - char const **argv = bear_strings_build(arg, &args); - va_end(args); - - bear_report_call(__func__, (char const *const *)argv); - int const result = call_execvp(file, (char *const *)argv); - - bear_strings_release(argv); - return result; -} -#endif - -#ifdef HAVE_EXECLE -# ifndef HAVE_EXECVE -# error can not implement execle without execve -# endif -// int execle(const char *path, const char *arg, ..., char * const envp[]); -int execle(const char *path, const char *arg, ...) { - va_list args; - va_start(args, arg); - char const **argv = bear_strings_build(arg, &args); - char const **envp = va_arg(args, char const **); - va_end(args); - - bear_report_call(__func__, (char const *const *)argv); - int const result = - call_execve(path, (char *const *)argv, (char *const *)envp); - - bear_strings_release(argv); - return result; -} -#endif - -#ifdef HAVE_POSIX_SPAWN -int posix_spawn(pid_t *restrict pid, const char *restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], char *const envp[restrict]) { - bear_report_call(__func__, (char const *const *)argv); - return call_posix_spawn(pid, path, file_actions, attrp, argv, envp); -} -#endif - -#ifdef HAVE_POSIX_SPAWNP -int posix_spawnp(pid_t *restrict pid, const char *restrict file, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], char *const envp[restrict]) { - bear_report_call(__func__, (char const *const *)argv); - return call_posix_spawnp(pid, file, file_actions, attrp, argv, envp); -} -#endif - -/* These are the methods which forward the call to the standard implementation. - */ - -#ifdef HAVE_EXECVE -static int call_execve(const char *path, char *const argv[], - char *const envp[]) { - typedef int (*func)(const char *, char *const *, char *const *); - - DLSYM(func, fp, "execve"); - - char const **const menvp = bear_update_environment(envp, &initial_env); - int const result = (*fp)(path, argv, (char *const *)menvp); - bear_strings_release(menvp); - return result; -} -#endif - -#ifdef HAVE_EXECVPE -static int call_execvpe(const char *file, char *const argv[], - char *const envp[]) { - typedef int (*func)(const char *, char *const *, char *const *); - - DLSYM(func, fp, "execvpe"); - - char const **const menvp = bear_update_environment(envp, &initial_env); - int const result = (*fp)(file, argv, (char *const *)menvp); - bear_strings_release(menvp); - return result; -} -#endif - -#ifdef HAVE_EXECVP -static int call_execvp(const char *file, char *const argv[]) { - typedef int (*func)(const char *file, char *const argv[]); - - DLSYM(func, fp, "execvp"); - - bear_env_t current_env; - bear_capture_env_t(¤t_env); - bear_reset_env_t(&initial_env); - int const result = (*fp)(file, argv); - bear_reset_env_t(¤t_env); - bear_release_env_t(¤t_env); - - return result; -} -#endif - -#ifdef HAVE_EXECVP2 -static int call_execvP(const char *file, const char *search_path, - char *const argv[]) { - typedef int (*func)(const char *, const char *, char *const *); - - DLSYM(func, fp, "execvP"); - - bear_env_t current_env; - bear_capture_env_t(¤t_env); - bear_reset_env_t(&initial_env); - int const result = (*fp)(file, search_path, argv); - bear_reset_env_t(¤t_env); - bear_release_env_t(¤t_env); - - return result; -} -#endif - -#ifdef HAVE_EXECT -static int call_exect(const char *path, char *const argv[], - char *const envp[]) { - typedef int (*func)(const char *, char *const *, char *const *); - - DLSYM(func, fp, "exect"); - - char const **const menvp = bear_update_environment(envp, &initial_env); - int const result = (*fp)(path, argv, (char *const *)menvp); - bear_strings_release(menvp); - return result; -} -#endif - -#ifdef HAVE_POSIX_SPAWN -static int call_posix_spawn(pid_t *restrict pid, const char *restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], - char *const envp[restrict]) { - typedef int (*func)(pid_t *restrict, const char *restrict, - const posix_spawn_file_actions_t *, - const posix_spawnattr_t *restrict, - char *const *restrict, char *const *restrict); - - DLSYM(func, fp, "posix_spawn"); - - char const **const menvp = bear_update_environment(envp, &initial_env); - int const result = - (*fp)(pid, path, file_actions, attrp, argv, (char *const *restrict)menvp); - bear_strings_release(menvp); - return result; -} -#endif - -#ifdef HAVE_POSIX_SPAWNP -static int call_posix_spawnp(pid_t *restrict pid, const char *restrict file, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *restrict attrp, - char *const argv[restrict], - char *const envp[restrict]) { - typedef int (*func)(pid_t *restrict, const char *restrict, - const posix_spawn_file_actions_t *, - const posix_spawnattr_t *restrict, - char *const *restrict, char *const *restrict); - - DLSYM(func, fp, "posix_spawnp"); - - char const **const menvp = bear_update_environment(envp, &initial_env); - int const result = - (*fp)(pid, file, file_actions, attrp, argv, (char *const *restrict)menvp); - bear_strings_release(menvp); - return result; -} -#endif - -/* this method is to write log about the process creation. */ - -static void bear_report_call(char const *fun, char const *const argv[]) { - static int const GS = 0x1d; - static int const RS = 0x1e; - static int const US = 0x1f; - - if (!initialized) - return; - - pthread_mutex_lock(&mutex); - const char *cwd = getcwd(NULL, 0); - if (0 == cwd) { - perror("bear: getcwd"); - exit(EXIT_FAILURE); - } - char const * const out_dir = initial_env[0]; - size_t const path_max_length = strlen(out_dir) + 32; - char filename[path_max_length]; - if (-1 == snprintf(filename, path_max_length, "%s/%d.cmd", out_dir, getpid())) { - perror("bear: snprintf"); - exit(EXIT_FAILURE); - } - FILE * fd = fopen(filename, "a+"); - if (0 == fd) { - perror("bear: fopen"); - exit(EXIT_FAILURE); - } - fprintf(fd, "%d%c", getpid(), RS); - fprintf(fd, "%d%c", getppid(), RS); - fprintf(fd, "%s%c", fun, RS); - fprintf(fd, "%s%c", cwd, RS); - size_t const argc = bear_strings_length(argv); - for (size_t it = 0; it < argc; ++it) { - fprintf(fd, "%s%c", argv[it], US); - } - fprintf(fd, "%c", GS); - if (fclose(fd)) { - perror("bear: fclose"); - exit(EXIT_FAILURE); - } - free((void *)cwd); - pthread_mutex_unlock(&mutex); -} - -/* update environment assure that chilren processes will copy the desired - * behaviour */ - -static int bear_capture_env_t(bear_env_t *env) { - int status = 1; - for (size_t it = 0; it < ENV_SIZE; ++it) { - char const * const env_value = getenv(env_names[it]); - char const * const env_copy = (env_value) ? strdup(env_value) : env_value; - (*env)[it] = env_copy; - status &= (env_copy) ? 1 : 0; - } - return status; -} - -static int bear_reset_env_t(bear_env_t *env) { - int status = 1; - for (size_t it = 0; it < ENV_SIZE; ++it) { - if ((*env)[it]) { - setenv(env_names[it], (*env)[it], 1); - } else { - unsetenv(env_names[it]); - } - } - return status; -} - -static void bear_release_env_t(bear_env_t *env) { - for (size_t it = 0; it < ENV_SIZE; ++it) { - free((void *)(*env)[it]); - (*env)[it] = 0; - } -} - -static char const **bear_update_environment(char *const envp[], bear_env_t *env) { - char const **result = bear_strings_copy((char const **)envp); - for (size_t it = 0; it < ENV_SIZE && (*env)[it]; ++it) - result = bear_update_environ(result, env_names[it], (*env)[it]); - return result; -} - -static char const **bear_update_environ(char const *envs[], char const *key, char const * const value) { - // find the key if it's there - size_t const key_length = strlen(key); - char const **it = envs; - for (; (it) && (*it); ++it) { - if ((0 == strncmp(*it, key, key_length)) && - (strlen(*it) > key_length) && ('=' == (*it)[key_length])) - break; - } - // allocate a environment entry - size_t const value_length = strlen(value); - size_t const env_length = key_length + value_length + 2; - char *env = malloc(env_length); - if (0 == env) { - perror("bear: malloc [in env_update]"); - exit(EXIT_FAILURE); - } - if (-1 == snprintf(env, env_length, "%s=%s", key, value)) { - perror("bear: snprintf"); - exit(EXIT_FAILURE); - } - // replace or append the environment entry - if (it && *it) { - free((void *)*it); - *it = env; - return envs; - } - return bear_strings_append(envs, env); -} - -static char **bear_get_environment() { -#if defined HAVE_NSGETENVIRON - return *_NSGetEnviron(); -#else - return environ; -#endif -} - -/* util methods to deal with string arrays. environment and process arguments - * are both represented as string arrays. */ - -static char const **bear_strings_build(char const *const arg, va_list *args) { - char const **result = 0; - size_t size = 0; - for (char const *it = arg; it; it = va_arg(*args, char const *)) { - result = realloc(result, (size + 1) * sizeof(char const *)); - if (0 == result) { - perror("bear: realloc"); - exit(EXIT_FAILURE); - } - char const *copy = strdup(it); - if (0 == copy) { - perror("bear: strdup"); - exit(EXIT_FAILURE); - } - result[size++] = copy; - } - result = realloc(result, (size + 1) * sizeof(char const *)); - if (0 == result) { - perror("bear: realloc"); - exit(EXIT_FAILURE); - } - result[size++] = 0; - - return result; -} - -static char const **bear_strings_copy(char const **const in) { - size_t const size = bear_strings_length(in); - - char const **const result = malloc((size + 1) * sizeof(char const *)); - if (0 == result) { - perror("bear: malloc"); - exit(EXIT_FAILURE); - } - - char const **out_it = result; - for (char const *const *in_it = in; (in_it) && (*in_it); - ++in_it, ++out_it) { - *out_it = strdup(*in_it); - if (0 == *out_it) { - perror("bear: strdup"); - exit(EXIT_FAILURE); - } - } - *out_it = 0; - return result; -} - -static char const **bear_strings_append(char const **const in, - char const *const e) { - size_t size = bear_strings_length(in); - char const **result = realloc(in, (size + 2) * sizeof(char const *)); - if (0 == result) { - perror("bear: realloc"); - exit(EXIT_FAILURE); - } - result[size++] = e; - result[size++] = 0; - return result; -} - -static size_t bear_strings_length(char const *const *const in) { - size_t result = 0; - for (char const *const *it = in; (it) && (*it); ++it) - ++result; - return result; -} - -static void bear_strings_release(char const **in) { - for (char const *const *it = in; (it) && (*it); ++it) { - free((void *)*it); - } - free((void *)in); -} Index: clang/tools/scan-build-py/lib/libscanbuild/resources/sorttable.js =================================================================== --- /dev/null +++ clang/tools/scan-build-py/lib/libscanbuild/resources/sorttable.js @@ -0,0 +1,535 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add <script src="sorttable.js"></script> to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + +var stIsIE = /*@cc_on!@*/ false; + +sorttable = { + init : function() { + // quit if this function has already been called + if (arguments.callee.done) + return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) + clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) + return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + }, + + makeSortable : function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the, table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) + table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) + return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i = 0; i < table.rows.length; i++) { + if (table.rows[i].className.search(/\bsortbottom\b/) != -1) { + sortbottomrows[sortbottomrows.length] = table.rows[i]; + } + } + if (sortbottomrows) { + if (table.tFoot == null) { + // table doesn't have a tfoot. Create one. + tfo = document.createElement('tfoot'); + table.appendChild(tfo); + } + for (var i = 0; i < sortbottomrows.length; i++) { + tfo.appendChild(sortbottomrows[i]); + } + delete sortbottomrows; + } + + // work through each column and calculate its type + headrow = table.tHead.rows[0].cells; + for (var i = 0; i < headrow.length; i++) { + // manually override the type with a sorttable_type attribute + if (!headrow[i].className.match( + /\bsorttable_nosort\b/)) { // skip this col + mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/); + if (mtch) { + override = mtch[1]; + } + if (mtch && typeof sorttable["sort_" + override] == 'function') { + headrow[i].sorttable_sortfunction = sorttable["sort_" + override]; + } else { + headrow[i].sorttable_sortfunction = sorttable.guessType(table, i); + } + // make it clickable to sort + headrow[i].sorttable_columnindex = i; + headrow[i].sorttable_tbody = table.tBodies[0]; + dean_addEvent(headrow[i], "click", function(e) { + if (this.className.search(/\bsorttable_sorted\b/) != -1) { + // if we're already sorted by this column, just + // reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted', + 'sorttable_sorted_reverse'); + this.removeChild(document.getElementById('sorttable_sortfwdind')); + sortrevind = document.createElement('span'); + sortrevind.id = "sorttable_sortrevind"; + sortrevind.innerHTML = stIsIE + ? ' <font face="webdings">5</font>' + : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE + ? ' <font face="webdings">6</font>' + : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = + cell.className.replace('sorttable_sorted_reverse', ''); + cell.className = cell.className.replace('sorttable_sorted', ''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { + sortfwdind.parentNode.removeChild(sortfwdind); + } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { + sortrevind.parentNode.removeChild(sortrevind); + } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = + stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j = 0; j < rows.length; j++) { + row_array[row_array.length] = + [ sorttable.getInnerText(rows[j].cells[col]), rows[j] ]; + } + /* If you want a stable sort, uncomment the following line */ + sorttable.shaker_sort(row_array, this.sorttable_sortfunction); + /* and comment out this one */ + // row_array.sort(this.sorttable_sortfunction); + + tb = this.sorttable_tbody; + for (var j = 0; j < row_array.length; j++) { + tb.appendChild(row_array[j][1]); + } + + delete row_array; + }); + } + } + }, + + guessType : function(table, column) { + // guess the type of a column based on its first non-blank row + sortfn = sorttable.sort_alpha; + for (var i = 0; i < table.tBodies[0].rows.length; i++) { + text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]); + if (text != '') { + if (text.match(/^-?[ï½£$、]?[\d,.]+%?$/)) { + return sorttable.sort_numeric; + } + // check for a date: dd/mm/yyyy or dd/mm/yy + // can have / or . or - as separator + // can be mm/dd as well + possdate = text.match(sorttable.DATE_RE) + if (possdate) { + // looks like a date + first = parseInt(possdate[1]); + second = parseInt(possdate[2]); + if (first > 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText : function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for <input> fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse : function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i = 0; i < tbody.rows.length; i++) { + newrows[newrows.length] = tbody.rows[i]; + } + for (var i = newrows.length - 1; i >= 0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric : function(a, b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g, '')); + if (isNaN(aa)) + aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g, '')); + if (isNaN(bb)) + bb = 0; + return aa - bb; + }, + sort_alpha : function(a, b) { + if (a[0] == b[0]) + return 0; + if (a[0] < b[0]) + return -1; + return 1; + }, + sort_ddmm : function(a, b) { + mtch = a[0].match(sorttable.DATE_RE); + y = mtch[3]; + m = mtch[2]; + d = mtch[1]; + if (m.length == 1) + m = '0' + m; + if (d.length == 1) + d = '0' + d; + dt1 = y + m + d; + mtch = b[0].match(sorttable.DATE_RE); + y = mtch[3]; + m = mtch[2]; + d = mtch[1]; + if (m.length == 1) + m = '0' + m; + if (d.length == 1) + d = '0' + d; + dt2 = y + m + d; + if (dt1 == dt2) + return 0; + if (dt1 < dt2) + return -1; + return 1; + }, + sort_mmdd : function(a, b) { + mtch = a[0].match(sorttable.DATE_RE); + y = mtch[3]; + d = mtch[2]; + m = mtch[1]; + if (m.length == 1) + m = '0' + m; + if (d.length == 1) + d = '0' + d; + dt1 = y + m + d; + mtch = b[0].match(sorttable.DATE_RE); + y = mtch[3]; + d = mtch[2]; + m = mtch[1]; + if (m.length == 1) + m = '0' + m; + if (d.length == 1) + d = '0' + d; + dt2 = y + m + d; + if (dt1 == dt2) + return 0; + if (dt1 < dt2) + return -1; + return 1; + }, + + shaker_sort : function(list, comp_func) { + // A stable sort function to allow multi-level sorting of data + // see: http://en.wikipedia.org/wiki/Cocktail_sort + // thanks to Joseph Nahmias + var b = 0; + var t = list.length - 1; + var swap = true; + + while (swap) { + swap = false; + for (var i = b; i < t; ++i) { + if (comp_func(list[i], list[i + 1]) > 0) { + var q = list[i]; + list[i] = list[i + 1]; + list[i + 1] = q; + swap = true; + } + } // for + t--; + + if (!swap) + break; + + for (var i = t; i > b; --i) { + if (comp_func(list[i], list[i - 1]) < 0) { + var q = list[i]; + list[i] = list[i - 1]; + list[i - 1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write("<script id=__ie_onload defer +src=javascript:void(0)><\/script>"); var script = +document.getElementById("__ie_onload"); script.onreadystatechange = function() { + if (this.readyState == "complete") { + sorttable.init(); // call the onload handler + } + }; +/*@end @*/ + +/* for Safari */ +if (/WebKit/i.test(navigator.userAgent)) { // sniff + var _timer = setInterval(function() { + if (/loaded|complete/.test(document.readyState)) { + sorttable.init(); // call the onload handler + } + }, 10); +} + +/* for other browsers */ +window.onload = sorttable.init; + +// written by Dean Edwards, 2005 +// with input from Tino Zijdel, Matthias Miller, Diego Perini + +// http://dean.edwards.name/weblog/2005/10/add-event/ + +function dean_addEvent(element, type, handler) { + if (element.addEventListener) { + element.addEventListener(type, handler, false); + } else { + // assign each event handler a unique ID + if (!handler.$$guid) + handler.$$guid = dean_addEvent.guid++; + // create a hash table of event types for the element + if (!element.events) + element.events = {}; + // create a hash table of event handlers for each element/event pair + var handlers = element.events[type]; + if (!handlers) { + handlers = element.events[type] = {}; + // store the existing event handler (if there is one) + if (element["on" + type]) { + handlers[0] = element["on" + type]; + } + } + // store the event handler in the hash table + handlers[handler.$$guid] = handler; + // assign a global event handler to do all the work + element["on" + type] = handleEvent; + } +}; +// a counter used to create unique IDs +dean_addEvent.guid = 1; + +function removeEvent(element, type, handler) { + if (element.removeEventListener) { + element.removeEventListener(type, handler, false); + } else { + // delete the event handler from the hash table + if (element.events && element.events[type]) { + delete element.events[type][handler.$$guid]; + } + } +}; + +function handleEvent(event) { + var returnValue = true; + // grab the event object (IE uses a global event object) + event = + event || + fixEvent( + ((this.ownerDocument || this.document || this).parentWindow || window) + .event); + // get a reference to the hash table of event handlers + var handlers = this.events[event.type]; + // execute each event handler + for (var i in handlers) { + this.$$handleEvent = handlers[i]; + if (this.$$handleEvent(event) === false) { + returnValue = false; + } + } + return returnValue; +}; + +function fixEvent(event) { + // add W3C standard event methods + event.preventDefault = fixEvent.preventDefault; + event.stopPropagation = fixEvent.stopPropagation; + return event; +}; +fixEvent.preventDefault = function() { this.returnValue = false; }; +fixEvent.stopPropagation = function() { this.cancelBubble = true; } + +// Dean's forEach: http://dean.edwards.name/base/forEach.js +/* + forEach, version 1.0 + Copyright 2006, Dean Edwards + License: http://www.opensource.org/licenses/mit-license.php +*/ + +// array-like enumeration +if (!Array.forEach) { // mozilla already supports this + Array.forEach = function(array, block, context) { + for (var i = 0; i < array.length; i++) { + block.call(context, array[i], i, array); + } + }; +} + +// generic enumeration +Function.prototype.forEach = function(object, block, context) { + for (var key in object) { + if (typeof this.prototype[key] == "undefined") { + block.call(context, object[key], key, object); + } + } +}; + +// character enumeration +String.forEach = function(string, block, context) { + Array.forEach( + string.split(""), + function(chr, index) { block.call(context, chr, index, string); }); +}; + +// globally resolve forEach enumeration +var forEach = function(object, block, context) { + if (object) { + var resolve = Object; // default + if (object instanceof Function) { + // functions have a "length" property + resolve = Function; + } else if (object.forEach instanceof Function) { + // the object implements a custom forEach method so use that + object.forEach(block, context); + return; + } else if (typeof object == "string") { + // the object is a string + resolve = String; + } else if (typeof object.length == "number") { + // the object is array-like + resolve = Array; + } + resolve.forEach(object, block, context); + } +}; Index: clang/tools/scan-build-py/lib/libscanbuild/resources/selectable.js =================================================================== --- clang/tools/scan-build-py/lib/libscanbuild/resources/selectable.js +++ clang/tools/scan-build-py/lib/libscanbuild/resources/selectable.js @@ -1,7 +1,6 @@ -function SetDisplay(RowClass, DisplayVal) -{ +function SetDisplay(RowClass, DisplayVal) { var Rows = document.getElementsByTagName("tr"); - for ( var i = 0 ; i < Rows.length; ++i ) { + for (var i = 0; i < Rows.length; ++i) { if (Rows[i].className == RowClass) { Rows[i].style.display = DisplayVal; } @@ -10,24 +9,24 @@ function CopyCheckedStateToCheckButtons(SummaryCheckButton) { var Inputs = document.getElementsByTagName("input"); - for ( var i = 0 ; i < Inputs.length; ++i ) { + for (var i = 0; i < Inputs.length; ++i) { if (Inputs[i].type == "checkbox") { - if(Inputs[i] != SummaryCheckButton) { + if (Inputs[i] != SummaryCheckButton) { Inputs[i].checked = SummaryCheckButton.checked; Inputs[i].onclick(); - } + } } } } -function returnObjById( id ) { - if (document.getElementById) - var returnVar = document.getElementById(id); - else if (document.all) - var returnVar = document.all[id]; - else if (document.layers) - var returnVar = document.layers[id]; - return returnVar; +function returnObjById(id) { + if (document.getElementById) + var returnVar = document.getElementById(id); + else if (document.all) + var returnVar = document.all[id]; + else if (document.layers) + var returnVar = document.layers[id]; + return returnVar; } var NumUnchecked = 0; @@ -38,8 +37,7 @@ if (--NumUnchecked == 0) { returnObjById("AllBugsCheck").checked = true; } - } - else { + } else { SetDisplay(ClassName, "none"); NumUnchecked++; returnObjById("AllBugsCheck").checked = false; Index: clang/tools/scan-build-py/lib/libear/ear.c =================================================================== --- /dev/null +++ clang/tools/scan-build-py/lib/libear/ear.c @@ -0,0 +1,600 @@ +/* -*- coding: utf-8 -*- +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +/** + * This file implements a shared library. This library can be pre-loaded by + * the dynamic linker of the Operating System (OS). It implements a few function + * related to process creation. By pre-load this library the executed process + * uses these functions instead of those from the standard library. + * + * The idea here is to inject a logic before call the real methods. The logic is + * to dump the call into a file. To call the real method this library is doing + * the job of the dynamic linker. + * + * The only input for the log writing is about the destination directory. + * This is passed as environment variable. + */ + +#include "config.h" + +#include <dlfcn.h> +#include <pthread.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if defined HAVE_POSIX_SPAWN || defined HAVE_POSIX_SPAWNP +#include <spawn.h> +#endif + +#if defined HAVE_NSGETENVIRON +#include <crt_externs.h> +#else +extern char **environ; +#endif + +#define ENV_OUTPUT "INTERCEPT_BUILD_TARGET_DIR" +#ifdef APPLE +#define ENV_FLAT "DYLD_FORCE_FLAT_NAMESPACE" +#define ENV_PRELOAD "DYLD_INSERT_LIBRARIES" +#define ENV_SIZE 3 +#else +#define ENV_PRELOAD "LD_PRELOAD" +#define ENV_SIZE 2 +#endif + +#define DLSYM(TYPE_, VAR_, SYMBOL_) \ + union { \ + void *from; \ + TYPE_ to; \ + } cast; \ + if (0 == (cast.from = dlsym(RTLD_NEXT, SYMBOL_))) { \ + perror("bear: dlsym"); \ + exit(EXIT_FAILURE); \ + } \ + TYPE_ const VAR_ = cast.to; + +typedef char const *bear_env_t[ENV_SIZE]; + +static int bear_capture_env_t(bear_env_t *env); +static int bear_reset_env_t(bear_env_t *env); +static void bear_release_env_t(bear_env_t *env); +static char const **bear_update_environment(char *const envp[], + bear_env_t *env); +static char const **bear_update_environ(char const **in, char const *key, + char const *value); +static char **bear_get_environment(); +static void bear_report_call(char const *fun, char const *const argv[]); +static char const **bear_strings_build(char const *arg, va_list *ap); +static char const **bear_strings_copy(char const **const in); +static char const **bear_strings_append(char const **in, char const *e); +static size_t bear_strings_length(char const *const *in); +static void bear_strings_release(char const **); + +static bear_env_t env_names = {ENV_OUTPUT, ENV_PRELOAD +#ifdef ENV_FLAT + , + ENV_FLAT +#endif +}; + +static bear_env_t initial_env = {0, 0 +#ifdef ENV_FLAT + , + 0 +#endif +}; + +static int initialized = 0; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +static void on_load(void) __attribute__((constructor)); +static void on_unload(void) __attribute__((destructor)); + +#ifdef HAVE_EXECVE +static int call_execve(const char *path, char *const argv[], + char *const envp[]); +#endif +#ifdef HAVE_EXECVP +static int call_execvp(const char *file, char *const argv[]); +#endif +#ifdef HAVE_EXECVPE +static int call_execvpe(const char *file, char *const argv[], + char *const envp[]); +#endif +#ifdef HAVE_EXECVP2 +static int call_execvP(const char *file, const char *search_path, + char *const argv[]); +#endif +#ifdef HAVE_EXECT +static int call_exect(const char *path, char *const argv[], char *const envp[]); +#endif +#ifdef HAVE_POSIX_SPAWN +static int call_posix_spawn(pid_t *restrict pid, const char *restrict path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict]); +#endif +#ifdef HAVE_POSIX_SPAWNP +static int call_posix_spawnp(pid_t *restrict pid, const char *restrict file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict]); +#endif + +/* Initialization method to Captures the relevant environment variables. + */ + +static void on_load(void) { + pthread_mutex_lock(&mutex); + if (!initialized) + initialized = bear_capture_env_t(&initial_env); + pthread_mutex_unlock(&mutex); +} + +static void on_unload(void) { + pthread_mutex_lock(&mutex); + bear_release_env_t(&initial_env); + initialized = 0; + pthread_mutex_unlock(&mutex); +} + +/* These are the methods we are try to hijack. + */ + +#ifdef HAVE_EXECVE +int execve(const char *path, char *const argv[], char *const envp[]) { + bear_report_call(__func__, (char const *const *)argv); + return call_execve(path, argv, envp); +} +#endif + +#ifdef HAVE_EXECV +#ifndef HAVE_EXECVE +#error can not implement execv without execve +#endif +int execv(const char *path, char *const argv[]) { + bear_report_call(__func__, (char const *const *)argv); + char *const *envp = bear_get_environment(); + return call_execve(path, argv, envp); +} +#endif + +#ifdef HAVE_EXECVPE +int execvpe(const char *file, char *const argv[], char *const envp[]) { + bear_report_call(__func__, (char const *const *)argv); + return call_execvpe(file, argv, envp); +} +#endif + +#ifdef HAVE_EXECVP +int execvp(const char *file, char *const argv[]) { + bear_report_call(__func__, (char const *const *)argv); + return call_execvp(file, argv); +} +#endif + +#ifdef HAVE_EXECVP2 +int execvP(const char *file, const char *search_path, char *const argv[]) { + bear_report_call(__func__, (char const *const *)argv); + return call_execvP(file, search_path, argv); +} +#endif + +#ifdef HAVE_EXECT +int exect(const char *path, char *const argv[], char *const envp[]) { + bear_report_call(__func__, (char const *const *)argv); + return call_exect(path, argv, envp); +} +#endif + +#ifdef HAVE_EXECL +#ifndef HAVE_EXECVE +#error can not implement execl without execve +#endif +int execl(const char *path, const char *arg, ...) { + va_list args; + va_start(args, arg); + char const **argv = bear_strings_build(arg, &args); + va_end(args); + + bear_report_call(__func__, (char const *const *)argv); + char *const *envp = bear_get_environment(); + int const result = call_execve(path, (char *const *)argv, envp); + + bear_strings_release(argv); + return result; +} +#endif + +#ifdef HAVE_EXECLP +#ifndef HAVE_EXECVP +#error can not implement execlp without execvp +#endif +int execlp(const char *file, const char *arg, ...) { + va_list args; + va_start(args, arg); + char const **argv = bear_strings_build(arg, &args); + va_end(args); + + bear_report_call(__func__, (char const *const *)argv); + int const result = call_execvp(file, (char *const *)argv); + + bear_strings_release(argv); + return result; +} +#endif + +#ifdef HAVE_EXECLE +#ifndef HAVE_EXECVE +#error can not implement execle without execve +#endif +// int execle(const char *path, const char *arg, ..., char * const envp[]); +int execle(const char *path, const char *arg, ...) { + va_list args; + va_start(args, arg); + char const **argv = bear_strings_build(arg, &args); + char const **envp = va_arg(args, char const **); + va_end(args); + + bear_report_call(__func__, (char const *const *)argv); + int const result = + call_execve(path, (char *const *)argv, (char *const *)envp); + + bear_strings_release(argv); + return result; +} +#endif + +#ifdef HAVE_POSIX_SPAWN +int posix_spawn(pid_t *restrict pid, const char *restrict path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], char *const envp[restrict]) { + bear_report_call(__func__, (char const *const *)argv); + return call_posix_spawn(pid, path, file_actions, attrp, argv, envp); +} +#endif + +#ifdef HAVE_POSIX_SPAWNP +int posix_spawnp(pid_t *restrict pid, const char *restrict file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], char *const envp[restrict]) { + bear_report_call(__func__, (char const *const *)argv); + return call_posix_spawnp(pid, file, file_actions, attrp, argv, envp); +} +#endif + +/* These are the methods which forward the call to the standard implementation. + */ + +#ifdef HAVE_EXECVE +static int call_execve(const char *path, char *const argv[], + char *const envp[]) { + typedef int (*func)(const char *, char *const *, char *const *); + + DLSYM(func, fp, "execve"); + + char const **const menvp = bear_update_environment(envp, &initial_env); + int const result = (*fp)(path, argv, (char *const *)menvp); + bear_strings_release(menvp); + return result; +} +#endif + +#ifdef HAVE_EXECVPE +static int call_execvpe(const char *file, char *const argv[], + char *const envp[]) { + typedef int (*func)(const char *, char *const *, char *const *); + + DLSYM(func, fp, "execvpe"); + + char const **const menvp = bear_update_environment(envp, &initial_env); + int const result = (*fp)(file, argv, (char *const *)menvp); + bear_strings_release(menvp); + return result; +} +#endif + +#ifdef HAVE_EXECVP +static int call_execvp(const char *file, char *const argv[]) { + typedef int (*func)(const char *file, char *const argv[]); + + DLSYM(func, fp, "execvp"); + + bear_env_t current_env; + bear_capture_env_t(¤t_env); + bear_reset_env_t(&initial_env); + int const result = (*fp)(file, argv); + bear_reset_env_t(¤t_env); + bear_release_env_t(¤t_env); + + return result; +} +#endif + +#ifdef HAVE_EXECVP2 +static int call_execvP(const char *file, const char *search_path, + char *const argv[]) { + typedef int (*func)(const char *, const char *, char *const *); + + DLSYM(func, fp, "execvP"); + + bear_env_t current_env; + bear_capture_env_t(¤t_env); + bear_reset_env_t(&initial_env); + int const result = (*fp)(file, search_path, argv); + bear_reset_env_t(¤t_env); + bear_release_env_t(¤t_env); + + return result; +} +#endif + +#ifdef HAVE_EXECT +static int call_exect(const char *path, char *const argv[], + char *const envp[]) { + typedef int (*func)(const char *, char *const *, char *const *); + + DLSYM(func, fp, "exect"); + + char const **const menvp = bear_update_environment(envp, &initial_env); + int const result = (*fp)(path, argv, (char *const *)menvp); + bear_strings_release(menvp); + return result; +} +#endif + +#ifdef HAVE_POSIX_SPAWN +static int call_posix_spawn(pid_t *restrict pid, const char *restrict path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict]) { + typedef int (*func)(pid_t *restrict, const char *restrict, + const posix_spawn_file_actions_t *, + const posix_spawnattr_t *restrict, char *const *restrict, + char *const *restrict); + + DLSYM(func, fp, "posix_spawn"); + + char const **const menvp = bear_update_environment(envp, &initial_env); + int const result = + (*fp)(pid, path, file_actions, attrp, argv, (char *const *restrict)menvp); + bear_strings_release(menvp); + return result; +} +#endif + +#ifdef HAVE_POSIX_SPAWNP +static int call_posix_spawnp(pid_t *restrict pid, const char *restrict file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict]) { + typedef int (*func)(pid_t *restrict, const char *restrict, + const posix_spawn_file_actions_t *, + const posix_spawnattr_t *restrict, char *const *restrict, + char *const *restrict); + + DLSYM(func, fp, "posix_spawnp"); + + char const **const menvp = bear_update_environment(envp, &initial_env); + int const result = + (*fp)(pid, file, file_actions, attrp, argv, (char *const *restrict)menvp); + bear_strings_release(menvp); + return result; +} +#endif + +/* this method is to write log about the process creation. */ + +static void bear_report_call(char const *fun, char const *const argv[]) { + static int const GS = 0x1d; + static int const RS = 0x1e; + static int const US = 0x1f; + + if (!initialized) + return; + + pthread_mutex_lock(&mutex); + const char *cwd = getcwd(NULL, 0); + if (0 == cwd) { + perror("bear: getcwd"); + exit(EXIT_FAILURE); + } + char const *const out_dir = initial_env[0]; + size_t const path_max_length = strlen(out_dir) + 32; + char filename[path_max_length]; + if (-1 == + snprintf(filename, path_max_length, "%s/%d.cmd", out_dir, getpid())) { + perror("bear: snprintf"); + exit(EXIT_FAILURE); + } + FILE *fd = fopen(filename, "a+"); + if (0 == fd) { + perror("bear: fopen"); + exit(EXIT_FAILURE); + } + fprintf(fd, "%d%c", getpid(), RS); + fprintf(fd, "%d%c", getppid(), RS); + fprintf(fd, "%s%c", fun, RS); + fprintf(fd, "%s%c", cwd, RS); + size_t const argc = bear_strings_length(argv); + for (size_t it = 0; it < argc; ++it) { + fprintf(fd, "%s%c", argv[it], US); + } + fprintf(fd, "%c", GS); + if (fclose(fd)) { + perror("bear: fclose"); + exit(EXIT_FAILURE); + } + free((void *)cwd); + pthread_mutex_unlock(&mutex); +} + +/* update environment assure that chilren processes will copy the desired + * behaviour */ + +static int bear_capture_env_t(bear_env_t *env) { + int status = 1; + for (size_t it = 0; it < ENV_SIZE; ++it) { + char const *const env_value = getenv(env_names[it]); + char const *const env_copy = (env_value) ? strdup(env_value) : env_value; + (*env)[it] = env_copy; + status &= (env_copy) ? 1 : 0; + } + return status; +} + +static int bear_reset_env_t(bear_env_t *env) { + int status = 1; + for (size_t it = 0; it < ENV_SIZE; ++it) { + if ((*env)[it]) { + setenv(env_names[it], (*env)[it], 1); + } else { + unsetenv(env_names[it]); + } + } + return status; +} + +static void bear_release_env_t(bear_env_t *env) { + for (size_t it = 0; it < ENV_SIZE; ++it) { + free((void *)(*env)[it]); + (*env)[it] = 0; + } +} + +static char const **bear_update_environment(char *const envp[], + bear_env_t *env) { + char const **result = bear_strings_copy((char const **)envp); + for (size_t it = 0; it < ENV_SIZE && (*env)[it]; ++it) + result = bear_update_environ(result, env_names[it], (*env)[it]); + return result; +} + +static char const **bear_update_environ(char const *envs[], char const *key, + char const *const value) { + // find the key if it's there + size_t const key_length = strlen(key); + char const **it = envs; + for (; (it) && (*it); ++it) { + if ((0 == strncmp(*it, key, key_length)) && (strlen(*it) > key_length) && + ('=' == (*it)[key_length])) + break; + } + // allocate a environment entry + size_t const value_length = strlen(value); + size_t const env_length = key_length + value_length + 2; + char *env = malloc(env_length); + if (0 == env) { + perror("bear: malloc [in env_update]"); + exit(EXIT_FAILURE); + } + if (-1 == snprintf(env, env_length, "%s=%s", key, value)) { + perror("bear: snprintf"); + exit(EXIT_FAILURE); + } + // replace or append the environment entry + if (it && *it) { + free((void *)*it); + *it = env; + return envs; + } + return bear_strings_append(envs, env); +} + +static char **bear_get_environment() { +#if defined HAVE_NSGETENVIRON + return *_NSGetEnviron(); +#else + return environ; +#endif +} + +/* util methods to deal with string arrays. environment and process arguments + * are both represented as string arrays. */ + +static char const **bear_strings_build(char const *const arg, va_list *args) { + char const **result = 0; + size_t size = 0; + for (char const *it = arg; it; it = va_arg(*args, char const *)) { + result = realloc(result, (size + 1) * sizeof(char const *)); + if (0 == result) { + perror("bear: realloc"); + exit(EXIT_FAILURE); + } + char const *copy = strdup(it); + if (0 == copy) { + perror("bear: strdup"); + exit(EXIT_FAILURE); + } + result[size++] = copy; + } + result = realloc(result, (size + 1) * sizeof(char const *)); + if (0 == result) { + perror("bear: realloc"); + exit(EXIT_FAILURE); + } + result[size++] = 0; + + return result; +} + +static char const **bear_strings_copy(char const **const in) { + size_t const size = bear_strings_length(in); + + char const **const result = malloc((size + 1) * sizeof(char const *)); + if (0 == result) { + perror("bear: malloc"); + exit(EXIT_FAILURE); + } + + char const **out_it = result; + for (char const *const *in_it = in; (in_it) && (*in_it); ++in_it, ++out_it) { + *out_it = strdup(*in_it); + if (0 == *out_it) { + perror("bear: strdup"); + exit(EXIT_FAILURE); + } + } + *out_it = 0; + return result; +} + +static char const **bear_strings_append(char const **const in, + char const *const e) { + size_t size = bear_strings_length(in); + char const **result = realloc(in, (size + 2) * sizeof(char const *)); + if (0 == result) { + perror("bear: realloc"); + exit(EXIT_FAILURE); + } + result[size++] = e; + result[size++] = 0; + return result; +} + +static size_t bear_strings_length(char const *const *const in) { + size_t result = 0; + for (char const *const *it = in; (it) && (*it); ++it) + ++result; + return result; +} + +static void bear_strings_release(char const **in) { + for (char const *const *it = in; (it) && (*it); ++it) { + free((void *)*it); + } + free((void *)in); +} Index: clang/tools/scan-build-py/bin/scan-build =================================================================== --- clang/tools/scan-build-py/bin/scan-build +++ clang/tools/scan-build-py/bin/scan-build @@ -8,7 +8,7 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) from libscanbuild.analyze import scan_build Index: clang/tools/scan-build-py/bin/intercept-build =================================================================== --- clang/tools/scan-build-py/bin/intercept-build +++ clang/tools/scan-build-py/bin/intercept-build @@ -8,7 +8,7 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) from libscanbuild.intercept import intercept_build Index: clang/tools/scan-build-py/bin/analyze-build =================================================================== --- clang/tools/scan-build-py/bin/analyze-build +++ clang/tools/scan-build-py/bin/analyze-build @@ -8,7 +8,7 @@ import sys import os.path this_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.dirname(this_dir)) +sys.path.append(os.path.join(os.path.dirname(this_dir), 'lib')) from libscanbuild.analyze import analyze_build Index: clang/tools/scan-build-py/CMakeLists.txt =================================================================== --- /dev/null +++ clang/tools/scan-build-py/CMakeLists.txt @@ -0,0 +1,132 @@ +set (BinFiles + "analyze-build" + "intercept-build" + "scan-build") + +set (LibExecs + "analyze-c++" + "analyze-cc" + "intercept-c++" + "intercept-cc") + +set (LibScanbuild + "__init__.py" + "analyze.py" + "arguments.py" + "clang.py" + "compilation.py" + "intercept.py" + "report.py" + "shell.py") + +set (LibScanbuildResources + "scanview.css" + "selectable.js" + "sorttable.js") + +# libear is compiled dynamically in build_libear using the specified cc +# compiler. +set (LibEar + "__init__.py" + "config.h.in" + "ear.c") + +foreach(BinFile ${BinFiles}) + if ("${BinFile}" STREQUAL "scan-build") + # Need to rename scan-build to scan-build-py to prevent overwriting + # scan-build Perl implementation. + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/scan-build-py + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/bin/scan-build + ${CMAKE_BINARY_DIR}/bin/scan-build-py + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/scan-build) + install (PROGRAMS "bin/scan-build" + DESTINATION bin + RENAME scan-build-py + COMPONENT scan-build-py) + list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/scan-build-py) + else() + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${BinFile} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile} + ${CMAKE_BINARY_DIR}/bin/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile}) + install(PROGRAMS bin/${BinFile} + DESTINATION bin + COMPONENT scan-build-py) + list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${BinFile}) + endif() +endforeach() + +foreach(lib ${LibExecs}) + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/libexec/${lib} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/libexec + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${lib} + ${CMAKE_BINARY_DIR}/libexec/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${lib}) + list(APPEND Depends ${CMAKE_BINARY_DIR}/libexec/${lib}) + install(PROGRAMS libexec/${lib} + DESTINATION libexec + COMPONENT scan-build-py) +endforeach() + +foreach(lib ${LibScanbuild}) + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/lib/libscanbuild/${lib} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib/libscanbuild + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/lib/libscanbuild/${lib} + ${CMAKE_BINARY_DIR}/lib/libscanbuild/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/lib/libscanbuild/${lib}) + list(APPEND Depends ${CMAKE_BINARY_DIR}/lib/libscanbuild/${lib}) + install(PROGRAMS lib/libscanbuild/${lib} + DESTINATION lib/libscanbuild + COMPONENT scan-build-py) +endforeach() + +foreach(resource ${LibScanbuildResources}) + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/lib/libscanbuild/resources/${resource} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib/libscanbuild + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib/libscanbuild/resources + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/lib/libscanbuild/resources/${resource} + ${CMAKE_BINARY_DIR}/lib/libscanbuild/resources + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/lib/libscanbuild/resources/${resource}) + list(APPEND Depends ${CMAKE_BINARY_DIR}/lib/libscanbuild/resources/${resource}) + install(PROGRAMS lib/libscanbuild/resources/${resource} + DESTINATION lib/libscanbuild/resources + COMPONENT scan-build-py) +endforeach() + +foreach(lib ${LibEar}) + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/lib/libear/${lib} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/lib/libear + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/lib/libear/${lib} + ${CMAKE_BINARY_DIR}/lib/libear/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/lib/libear/${lib}) + list(APPEND Depends ${CMAKE_BINARY_DIR}/lib/libear/${lib}) + install(PROGRAMS lib/libear/${lib} + DESTINATION lib/libear + COMPONENT scan-build-py) +endforeach() + +add_custom_target(scan-build-py ALL DEPENDS ${Depends}) +add_llvm_install_targets("install-scan-build-py" + DEPENDS scan-build-py + COMPONENT scan-build-py) Index: clang/tools/CMakeLists.txt =================================================================== --- clang/tools/CMakeLists.txt +++ clang/tools/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_subdirectory(clang-check) add_clang_subdirectory(clang-extdef-mapping) add_clang_subdirectory(scan-build) + add_clang_subdirectory(scan-build-py) add_clang_subdirectory(scan-view) endif() Index: clang/cmake/caches/Fuchsia-stage2.cmake =================================================================== --- clang/cmake/caches/Fuchsia-stage2.cmake +++ clang/cmake/caches/Fuchsia-stage2.cmake @@ -278,6 +278,7 @@ llvm-symbolizer llvm-xray sancov + scan-build-py CACHE STRING "") set(LLVM_DISTRIBUTION_COMPONENTS
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits