diff --git a/.travis.yml b/.travis.yml index 1e4a18ea..06f8c3c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,6 @@ script : - mvn install -DskipTests - mvn verify sudo: false +addons: + sonarcloud: + organization: "lequal" diff --git a/README.md b/README.md index 46ac0fbc..3e8ffe59 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,42 @@ i-Code CNES is a static code analysis tool to help developers write code complia All the informations on CNES standards coverage, and rules availabilities and limitations can be read in the [documentation](https://github.com/lequal/i-CodeCNES/tree/master/documentation). +Release 3.1.0 +============= +## New features +* New command line #133 +* New parsing error handling, a violation named "Parser error" is added instead of suspend the analysis. #154 +* New rules (Shell) + * COM.DATA.Initialisation ( fix #113 ) + * COM.DATA.Invariant ( fix #114 ) + * COM.FLOW.FilePath ( fix #115 ) + * COM.FLOW.Recursion ( fix #116 ) + * COM.INST.BoolNegation ( fix #117 ) + * COM.NAME.Homonymy ( fix #118 ) + * COM.PRES.Indent ( fix #119 ) + * COM.PRES.LengthLine ( fix #120 ) + * SH.FLOW.CheckCodeReturn ( fix #121 ) + * SH.Ref.Export ( fix #122 #52 #138 #137) + * SH.SYNC.Signals #123 +* New metrics + * SH.MET.LineOfComment + * F77.MET.LineOfComment + * F90.MET.LineOfComment + +## Fixes +* Shell + * All checkers : + * Function correction on FUNCSTART and FNAME #138 #137 #150 + * COM.FLOW.CaseSwitch : + * Case handling fixed #135 + * Function localization fixed #52 + * COM.DATA.LoopCondition + * Function localization fixed #52 + * COM.DESIGN.ActiveWait + * Function localization fixed #52 + * COM.FLOW.Abort + * Function localization fixed #52 + Release 3.0.1 ============= * Fix of Eclipse's plug-in performances #101 diff --git a/documentation/i-Code CNES - Manuel Utilisateur.pdf b/documentation/i-Code CNES - Manuel Utilisateur.pdf deleted file mode 100644 index 7422414b..00000000 Binary files a/documentation/i-Code CNES - Manuel Utilisateur.pdf and /dev/null differ diff --git a/documentation/i-Code CNES - User Manual - EN.pdf b/documentation/i-Code CNES - User Manual.pdf similarity index 74% rename from documentation/i-Code CNES - User Manual - EN.pdf rename to documentation/i-Code CNES - User Manual.pdf index b456d47d..ab74dc18 100644 Binary files a/documentation/i-Code CNES - User Manual - EN.pdf and b/documentation/i-Code CNES - User Manual.pdf differ diff --git a/fr.cnes.analysis.tools.analyzer/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.analyzer/META-INF/MANIFEST.MF index 1104995a..80b54425 100755 --- a/fr.cnes.analysis.tools.analyzer/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.analyzer/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES Analyzer Bundle-SymbolicName: fr.cnes.analysis.tools.analyzer;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.analyzer.Activator Require-Bundle: org.eclipse.core.resources, org.eclipse.core.runtime diff --git a/fr.cnes.analysis.tools.analyzer/plugin.xml b/fr.cnes.analysis.tools.analyzer/plugin.xml index 85fecb95..c687c63b 100755 --- a/fr.cnes.analysis.tools.analyzer/plugin.xml +++ b/fr.cnes.analysis.tools.analyzer/plugin.xml @@ -3,5 +3,23 @@ + + + + + + + + diff --git a/fr.cnes.analysis.tools.analyzer/pom.xml b/fr.cnes.analysis.tools.analyzer/pom.xml index b425e681..e623e3bf 100644 --- a/fr.cnes.analysis.tools.analyzer/pom.xml +++ b/fr.cnes.analysis.tools.analyzer/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.analyzer diff --git a/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/CallableChecker.java b/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/CallableChecker.java index 495417d2..2c2bb221 100644 --- a/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/CallableChecker.java +++ b/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/CallableChecker.java @@ -14,6 +14,7 @@ import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.datas.ParsingError; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; import fr.cnes.analysis.tools.analyzer.logger.ICodeLogger; @@ -62,7 +63,17 @@ public List call() throws IOException, JFlexException { ICodeLogger.entering(CLASS, method); final List results = new ArrayList<>(); rule.setInputFile(file); - results.addAll(rule.run()); + try { + results.addAll(rule.run()); + } catch (JFlexException exception) { + ICodeLogger.error(exception.getFileName(), exception.getRuleName(), exception.getMessage()); + CheckResult result = new CheckResult(ParsingError.PARSING_ERROR_NAME,ParsingError.PARSING_ERROR_ID, ParsingError.PARSING_ERROR_LANGUAGE); + result.setLine(Integer.valueOf(exception.getLine())); + result.setLocation(exception.getRuleName() +"[l"+exception.getLine()+":c"+exception.getColumn()+"]"); + result.setMessage(exception.getErrorMessage()); + result.setFile(file); + results.add(result); + } ICodeLogger.exiting(CLASS, method, results); return results; } diff --git a/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/datas/ParsingError.java b/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/datas/ParsingError.java new file mode 100644 index 00000000..48495d11 --- /dev/null +++ b/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/datas/ParsingError.java @@ -0,0 +1,24 @@ +package fr.cnes.analysis.tools.analyzer.datas; + +import java.io.IOException; +import java.util.List; + +/** + * This rule is intended to add record parsing exceptions. + * + */ +public class ParsingError extends AbstractChecker { + + public final static String PARSING_ERROR_ID = "fr.cnes.analysis.tools.analyzer.parsingError"; + public final static String PARSING_ERROR_LANGUAGE = "fr.cnes.analysis.tools.analyzer.parsingError"; + public final static String PARSING_ERROR_NAME = "Parsing error"; + + public ParsingError() { + } + + + @Override + public List run() throws IOException { + return getCheckResults(); + } +} diff --git a/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/exception/JFlexException.java b/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/exception/JFlexException.java index 1003a4c3..178f9bbb 100755 --- a/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/exception/JFlexException.java +++ b/fr.cnes.analysis.tools.analyzer/src/fr/cnes/analysis/tools/analyzer/exception/JFlexException.java @@ -93,9 +93,9 @@ private static String errorMessage(String pRuleName, String pFileName, String pM + pMessage + BLANK + "CheckerId: " + pRuleName + BLANK + "File: " + pFileName + BLANK + "Line:" + pLine + BLANK + "Column:" + pColumn + BLANK - + "Last word scanned : [" + pLastScan + "] [" + toDecimalCode(pLastScan) + + "Last word scanned: [" + pLastScan + "] [" + toDecimalCode(pLastScan) + "]" + BLANK - + "Please report this issue on : https://github.com/dupuisa/i-CodeCNES/issues/"; + + "Please report this issue on : https://github.com/lequal/i-CodeCNES/issues/"; return message; } diff --git a/fr.cnes.analysis.tools.export.csv/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.export.csv/META-INF/MANIFEST.MF index 26205364..60b363c6 100644 --- a/fr.cnes.analysis.tools.export.csv/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.export.csv/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES CSV Export Bundle-SymbolicName: fr.cnes.analysis.tools.export.csv;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.export.csv.Activator Bundle-Vendor: CNES Require-Bundle: org.eclipse.core.runtime, diff --git a/fr.cnes.analysis.tools.export.csv/pom.xml b/fr.cnes.analysis.tools.export.csv/pom.xml index a584b026..1f8a6005 100644 --- a/fr.cnes.analysis.tools.export.csv/pom.xml +++ b/fr.cnes.analysis.tools.export.csv/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.export.csv diff --git a/fr.cnes.analysis.tools.export.xml/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.export.xml/META-INF/MANIFEST.MF index 3e1046e0..5a9501cc 100644 --- a/fr.cnes.analysis.tools.export.xml/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.export.xml/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES XML Export Bundle-SymbolicName: fr.cnes.analysis.tools.export.xml;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.export.xml.Activator Bundle-Vendor: CNES Require-Bundle: fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0", diff --git a/fr.cnes.analysis.tools.export.xml/pom.xml b/fr.cnes.analysis.tools.export.xml/pom.xml index ec7b7e01..fbf2568b 100644 --- a/fr.cnes.analysis.tools.export.xml/pom.xml +++ b/fr.cnes.analysis.tools.export.xml/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.export.xml diff --git a/fr.cnes.analysis.tools.export/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.export/META-INF/MANIFEST.MF index b9c73515..95d9243f 100644 --- a/fr.cnes.analysis.tools.export/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.export/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES Export Bundle-SymbolicName: fr.cnes.analysis.tools.export;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Vendor: CNES Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: fr.cnes.analysis.tools.analyzer, diff --git a/fr.cnes.analysis.tools.export/pom.xml b/fr.cnes.analysis.tools.export/pom.xml index 70a68570..2b73e4fc 100644 --- a/fr.cnes.analysis.tools.export/pom.xml +++ b/fr.cnes.analysis.tools.export/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.export diff --git a/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/ExportService.java b/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/ExportService.java index 6a6af8e2..b997453b 100644 --- a/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/ExportService.java +++ b/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/ExportService.java @@ -49,11 +49,24 @@ public class ExportService implements IExportService { public void export(List checkResults, File outputFile, Map parameters) throws NoContributorMatchingException, NoExtensionIndicatedException, IOException, CoreException { + export(checkResults, outputFile, parameters, + ExportUtils.getExtensionFromFilePath(outputFile.getAbsolutePath())); + } + + /* + * (non-Javadoc) + * + * @see fr.cnes.analysis.tools.export.IExportService#export(java.util.List, + * java.io.File, java.util.Map, java.lang.String) + */ + @Override + public void export(List pCheckResults, File pOutputFile, + Map pParameters, String pFormat) throws NoContributorMatchingException, + NoExtensionIndicatedException, IOException, CoreException { final String method = "export"; ICodeLogger.entering(CLASS, method); - final IExporter exporter = getExportClass( - ExportUtils.getExtensionFromFilePath(outputFile.getAbsolutePath())); - exporter.export(checkResults, outputFile, parameters); + final IExporter exporter = getExportClass(pFormat); + exporter.export(pCheckResults, pOutputFile, pParameters); ICodeLogger.exiting(CLASS, method); } diff --git a/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/IExportService.java b/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/IExportService.java index d4aec6b0..94f1707f 100644 --- a/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/IExportService.java +++ b/fr.cnes.analysis.tools.export/src/fr/cnes/analysis/tools/export/IExportService.java @@ -82,4 +82,32 @@ public boolean hasParameters(String formatExtension) */ public Map getParameters(String formatExtension) throws NoContributorMatchingException, CoreException; + + /** + * This function export each {@link CheckResult} of {@code checkResults} + * parameter into the {@link File} parameter. + * + * @param pCheckResults + * to export. + * @param pOutputFile + * to use for the export. + * @param pParameters + * parameter required by the export plugin. + * @param pFormat + * define the format of the results file. + * @throws NoContributorMatchingException + * when a format can not be handled by the @link + * {@link ExportService} service. + * @throws NoExtensionIndicatedException + * when the {@code outputFile} has no extension indicated. + * @throws IOException + * when the export failed due to a {@link java.io.File} + * exception. + * @throws CoreException + * when failing to create executable from contributor of + * {@link #EXPORT_EXTENSIONPOINT_ID}'s attribute + * {@link #EXPORT_EXTENSIONPOINT_ATTRIBUTE_EXPORTCLASS}. + */ + void export(List pCheckResults, File pOutputFile, Map pParameters, String pFormat) + throws NoContributorMatchingException, NoExtensionIndicatedException, IOException, CoreException; } diff --git a/fr.cnes.analysis.tools.fortran77.metrics/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.fortran77.metrics/META-INF/MANIFEST.MF index 6f109ecb..2f07183e 100755 --- a/fr.cnes.analysis.tools.fortran77.metrics/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.fortran77.metrics/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES F77 Metrics Bundle-SymbolicName: fr.cnes.analysis.tools.fortran77.metrics;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.fortran77.metrics.Activator Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0" diff --git a/fr.cnes.analysis.tools.fortran77.metrics/lex/F77METLineOfComment.lex b/fr.cnes.analysis.tools.fortran77.metrics/lex/F77METLineOfComment.lex new file mode 100644 index 00000000..88332677 --- /dev/null +++ b/fr.cnes.analysis.tools.fortran77.metrics/lex/F77METLineOfComment.lex @@ -0,0 +1,307 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ + +/********************************************************************************/ +/* This file is used to generate a metric checker for comment's rate. For */ +/* further information on this, we advise you to refer to CNES manual dealing */ +/* with metrics. */ +/* As many comments have been done on the RATEComment.lex file, this file */ +/* will restrain its comments on modifications. */ +/* */ +/********************************************************************************/ + +package fr.cnes.analysis.tools.fortran77.metrics; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.List; +import java.io.File; +import java.util.logging.Logger; + + +import org.eclipse.core.runtime.Path; + +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +%% + +%class F77METLineOfComment +%extends AbstractChecker +%public +%ignorecase +%column +%line + + +%function run +%yylexthrow JFlexException +%type List + + +%state COMMENT, NAMING, NEW_LINE, LINE, AVOID, DECL + +/* We add TYPE notion, which represent FUNC, PROC, SUB, MOD and PROG. */ +/* We also add END, which is used to ignore end of function, etc. */ +COMMENT_WORD = \! | "c" |\* +TYPE = "function" | "procedure" | "subroutine" | "program" | "module" |"interface" +FALSE = [a-zA-Z0-9\_]({TYPE}) | ({TYPE})[a-zA-Z0-9\_] | [a-zA-Z0-9\_]({TYPE})[a-zA-Z0-9\_] + | [^a-zA-Z0-9\_]("module")({SPACE}*)("procedure")[^a-zA-Z0-9\_] +SPACE = [\ \t\f] +VAR = [a-zA-Z][a-zA-Z0-9\_]* +STRING = \'[^\']*\' | \"[^\"]*\" + +END = END | end + +%{ + private static final Logger LOGGER = Logger.getLogger(F77METLineOfComment.class.getName()); + + + String location = "MAIN PROGRAM"; + private String parsedFileName; + Float numLines = 0.0f; + Float numComments = 0.0f; + Float numCommentTotal = 0.0f; + boolean endLine = true; + int functionLine = 0; + + + + public F77METLineOfComment() { + } + + @Override + public void setInputFile(File file) throws FileNotFoundException { + super.setInputFile(file); + LOGGER.finest("begin method setInputFile"); + this.parsedFileName = file.toString(); + this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); + this.parsedFileName = file.toString(); + LOGGER.finest("end method setInputFile"); + } + + private void endLocation() throws JFlexException{ + LOGGER.finest("begin method endLocation"); + final List list = this.getCheckResults(); + if (list.isEmpty()) { + + this.computeMetric(location, numComments, functionLine+1); + + } else { + final CheckResult last = list.get(list.size() - 1); + if (last.getLocation().equals(location)) { + + last.setValue(numComments); + + } else { + + this.computeMetric(location, numComments, functionLine+1); + + } + } + LOGGER.finest("end method endLocation"); + } + +%} + +/* At the end of analysis, atEOF is set at true. This is not meant to be modified. */ +%eofval{ + this.computeMetric(null, numCommentTotal, 0); + return getCheckResults(); +%eofval} + +%% + +/*********************/ +/* COMMENT PART */ +/*********************/ + + { + (\n|\r)+ { + + numComments++; + numCommentTotal++; + numLines++; + LOGGER.finest("Setting values [numComments ="+numComments+" | numLines = "+ numLines+"]"); + LOGGER.finest("COMMENT -> NEW_LINE (Transition : \\n | \\r)"); + yybegin(NEW_LINE); + } + . {} + } + +/*****************/ +/* AVOID PART */ +/*****************/ + + { + (\n|\r)+ { + numLines++; + LOGGER.finest("Setting value [numLines ="+numLines+"]"); + LOGGER.finest("AVOID -> NEW_LINE (Transition : \\n | \\r)"); + yybegin(NEW_LINE); + } + . {} + } + +/*****************/ +/* NAMING PART */ +/*****************/ + + { + {VAR} { + numLines = 0.0f; + numComments = 0.0f; + functionLine = yyline; + location = location + " " + yytext(); + LOGGER.finest("Setting values [numComments ="+numComments+" | numLines = "+ numLines+" | functionLine = "+ functionLine+" | location = "+ location+"]"); + LOGGER.finest("NAMING -> DECL (Transition : VAR)"); + yybegin(DECL); + } + (\n|\r)+ { + LOGGER.finest("NAMING -> NEW_LINE (Transition : \\n | \\r)"); + yybegin(NEW_LINE); + } + . {} + } + +/*****************/ +/* DECL STATE */ +/*****************/ + + { + "&"{SPACE}*[^\n\r] {} + "&" { + endLine = false; + LOGGER.finest("Setting value [endLine ="+endLine+"]"); + } + (\n|\r)+ { + if (endLine) { + LOGGER.finest("DECL -> NEW_LINE (Transition : \\n | \\r && endLine = true)"); + yybegin(NEW_LINE); + } + endLine = true; + LOGGER.finest("Setting value [endLine ="+endLine+"]"); + } + . {} + + } + +/*********************/ +/* INITIAL STATE */ +/*********************/ + + { + {COMMENT_WORD} { + LOGGER.finest("YYINITIAL -> COMMENT (Transition : COMMENT_WORD)"); + yybegin(COMMENT); + } + {STRING} { + LOGGER.finest("YYINITIAL -> LINE (Transition : STRING)"); + yybegin(LINE); + } + {FALSE} { + LOGGER.finest("YYINITIAL -> LINE (Transition : FALSE)"); + yybegin(LINE); + } + {TYPE} { + location = yytext(); + LOGGER.finest("Setting value [location ="+location+"]"); + LOGGER.finest("YYINITIAL -> NAMING (Transition : TYPE)"); + yybegin(NAMING); + } + {SPACE} { + LOGGER.finest("YYINITIAL -> NEW_LINE (Transition : SPACE)"); + yybegin(NEW_LINE); + } + (\n|\r)+ { + numLines = numLines + 1; + LOGGER.finest("Setting value [numLines ="+numLines+"]"); + LOGGER.finest("YYINITIAL -> NEW_LINE (Transition : \\n | \\r)"); + yybegin(NEW_LINE); + } + . { + LOGGER.finest("YYINITIAL -> NEW_LINE (Transition : .)"); + yybegin(LINE); + } + } + +/*********************/ +/* NEW_LINE STATE */ +/*********************/ + + { + {COMMENT_WORD} { + if (yycolumn == 0) { + LOGGER.finest("NEW_LINE -> COMMENT (Transition : COMMENT_WORD && yycolumn == 0)"); + yybegin(COMMENT); + } else { + LOGGER.finest("NEW_LINE -> LINE (Transition : COMMENT_WORD && yycolumn != 0)"); + yybegin(LINE); + } + } + {STRING} { + LOGGER.finest("NEW_LINE -> LINE (Transition : STRING"); + yybegin(LINE); + } + {FALSE} { + LOGGER.finest("NEW_LINE -> LINE (Transition : FALSE"); + yybegin(LINE); + } + {TYPE} { + location = yytext(); + LOGGER.finest("Setting value [location ="+location+"]"); + LOGGER.finest("NEW_LINE -> NAMING (Transition : TYPE"); + yybegin(NAMING); + } + {END} { + endLocation(); + LOGGER.finest("NEW_LINE -> AVOID (Transition : END"); + yybegin(AVOID); + } + {SPACE} {} + (\n|\r)+ {} + . { + LOGGER.finest("NEW_LINE -> LINE (Transition : ."); + yybegin(LINE); + } + } + +/*****************/ +/* LINE STATE */ +/*****************/ + + { + {STRING} {} + {FALSE} {} + {TYPE} { + location = yytext(); + LOGGER.finest("Setting value [location ="+location+"]"); + LOGGER.finest("LINE -> NAMING (Transition : TYPE"); + yybegin(NAMING); + } + {END} { + endLocation(); + LOGGER.finest("LINE -> AVOID (Transition : END"); + yybegin(AVOID); + } + (\n|\r)+ { + numLines = numLines + 1; + LOGGER.finest("Setting value [numLines ="+numLines+"]"); + LOGGER.finest("LINE -> NEW_LINE (Transition : \\n | \\r)"); + yybegin(NEW_LINE); + } + . {} + } + +/*********************/ +/* ERROR THROWN */ +/*********************/ + [^] { + + final String errorMessage = "Analysis failure : Your file could not be analyzed. Please verify that it was encoded in an UNIX format."; + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } \ No newline at end of file diff --git a/fr.cnes.analysis.tools.fortran77.metrics/plugin.xml b/fr.cnes.analysis.tools.fortran77.metrics/plugin.xml index 474ac61e..819db5b2 100755 --- a/fr.cnes.analysis.tools.fortran77.metrics/plugin.xml +++ b/fr.cnes.analysis.tools.fortran77.metrics/plugin.xml @@ -33,5 +33,12 @@ languageId="fr.cnes.analysis.tools.languages.f77" name="F77.MET.RatioComment"> + + diff --git a/fr.cnes.analysis.tools.fortran77.metrics/pom.xml b/fr.cnes.analysis.tools.fortran77.metrics/pom.xml index 6b2299d7..309c51b0 100644 --- a/fr.cnes.analysis.tools.fortran77.metrics/pom.xml +++ b/fr.cnes.analysis.tools.fortran77.metrics/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran77.metrics diff --git a/fr.cnes.analysis.tools.fortran77.rules/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.fortran77.rules/META-INF/MANIFEST.MF index 2f0833ff..ab56f482 100755 --- a/fr.cnes.analysis.tools.fortran77.rules/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.fortran77.rules/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES F77 Rules Bundle-SymbolicName: fr.cnes.analysis.tools.fortran77.rules;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.fortran77.rules.Activator Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0" diff --git a/fr.cnes.analysis.tools.fortran77.rules/pom.xml b/fr.cnes.analysis.tools.fortran77.rules/pom.xml index eeaf8068..8f7c5687 100644 --- a/fr.cnes.analysis.tools.fortran77.rules/pom.xml +++ b/fr.cnes.analysis.tools.fortran77.rules/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran77.rules diff --git a/fr.cnes.analysis.tools.fortran90.metrics/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.fortran90.metrics/META-INF/MANIFEST.MF index 37051b1f..f47f1535 100755 --- a/fr.cnes.analysis.tools.fortran90.metrics/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.fortran90.metrics/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES F90 Metrics Bundle-SymbolicName: fr.cnes.analysis.tools.fortran90.metrics;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.fortran90.metrics.Activator Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0" diff --git a/fr.cnes.analysis.tools.fortran90.metrics/lex/F90METLineOfComment.lex b/fr.cnes.analysis.tools.fortran90.metrics/lex/F90METLineOfComment.lex new file mode 100644 index 00000000..d7dbb022 --- /dev/null +++ b/fr.cnes.analysis.tools.fortran90.metrics/lex/F90METLineOfComment.lex @@ -0,0 +1,219 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ + +/********************************************************************************/ +/* This file is used to generate a metric checker for comment's rate. For */ +/* further information on this, we advise you to refer to CNES manual dealing */ +/* with metrics. */ +/* As many comments have been done on the RATEComment.lex file, this file */ +/* will restrain its comments on modifications. */ +/* */ +/********************************************************************************/ + +package fr.cnes.analysis.tools.fortran90.metrics; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.File; +import java.util.List; + +import org.eclipse.core.runtime.Path; + +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +%% + +%class F90METLineOfComment +%extends AbstractChecker +%public +%ignorecase +%column +%line + + +%function run +%yylexthrow JFlexException +%type List + +%state COMMENT, NAMING, NEW_LINE, LINE, AVOID, DECL + +/* We add TYPE notion, which represent FUNC, PROC, SUB, MOD and PROG. */ +/* We also add END, which is used to ignore end of function, etc. */ +COMMENT_WORD = \! +TYPE = "function" | "procedure" | "subroutine" | "program" | "module" |"interface" +FALSE = [a-zA-Z0-9\_]({TYPE}) | ({TYPE})[a-zA-Z0-9\_] | [a-zA-Z0-9\_]({TYPE})[a-zA-Z0-9\_] + | [^a-zA-Z0-9\_]("module")({SPACE}*)("procedure")[^a-zA-Z0-9\_] +SPACE = [\ \t\f] +VAR = [a-zA-Z][a-zA-Z0-9\_]* +STRING = \'[^\']*\' | \"[^\"]*\" + +END = END | end + +%{ + String location = "MAIN PROGRAM"; + private String parsedFileName; + Float numLines = 0.0f; + Float numComments = 0.0f; + Float numCommentTotal = 0.0f; + int functionLine = 0; + boolean endLine = true; + + public F90METLineOfComment() { + } + + @Override + public void setInputFile(File file) throws FileNotFoundException { + super.setInputFile(file); + this.parsedFileName = file.toString(); + this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); + } + // + private void endLocation() throws JFlexException { + final List list = this.getCheckResults(); + if (list.isEmpty()) { + + this.computeMetric(location, numComments, functionLine + 1); + + } else { + final CheckResult last = list.get(list.size() - 1); + if (last.getLocation().equals(location)) { + + last.setValue(numComments); + + } else { + + this.computeMetric(location, numComments, functionLine + 1); + + } + } + + + + + + } + +%} + +/* At the end of analysis, atEOF is set at true. This is not meant to be modified. */ +%eofval{ + this.computeMetric(null, numCommentTotal, 0); + return getCheckResults(); +%eofval} + +%% + +/*********************/ +/* COMMENT PART */ +/*********************/ + + { + (\n|\r)+ {numComments++; + numLines++; + numCommentTotal++; + yybegin(NEW_LINE);} + . {} + } + +/*****************/ +/* AVOID PART */ +/*****************/ + + { + (\n|\r)+ {numLines++; + yybegin(NEW_LINE);} + . {} + } + +/*****************/ +/* NAMING PART */ +/*****************/ + + { + {VAR} {numLines = 0.0f; + numComments = 0.0f; + location = location + " " + yytext(); + yybegin(DECL);} + (\n|\r)+ {yybegin(NEW_LINE);} + . {} + } + +/*****************/ +/* DECL STATE */ +/*****************/ + + { + "&"{SPACE}*[^\n\r] {} + "&" {endLine = false;} + (\n|\r)+ {if (endLine) { + yybegin(NEW_LINE); + } + endLine = true; + } + . {} + + } + +/*********************/ +/* INITIAL STATE */ +/*********************/ + + { + {COMMENT_WORD} {yybegin(COMMENT);} + {STRING} {yybegin(LINE);} + {FALSE} {yybegin(LINE);} + {TYPE} {location = yytext(); functionLine = yyline; + yybegin(NAMING);} + {SPACE} {yybegin(NEW_LINE);} + (\n|\r)+ {numLines = numLines + 1; + yybegin(NEW_LINE);} + . {yybegin(LINE);} + } + +/*********************/ +/* NEW_LINE STATE */ +/*********************/ + + { + {COMMENT_WORD} {yybegin(COMMENT);} + {STRING} {yybegin(LINE);} + {FALSE} {yybegin(LINE);} + {TYPE} {location = yytext(); functionLine = yyline; + yybegin(NAMING);} + {END} {endLocation(); + yybegin(AVOID);} + {SPACE} {} + (\n|\r)+ {} + . {yybegin(LINE);} + } + +/*****************/ +/* LINE STATE */ +/*****************/ + + { + {STRING} {} + {FALSE} {} + {TYPE} {location = yytext(); functionLine = yyline; + yybegin(NAMING);} + {END} {endLocation(); + yybegin(AVOID);} + (\n|\r)+ {numLines = numLines + 1; + yybegin(NEW_LINE);} + . {} + } + +/*********************/ +/* ERROR THROWN */ +/*********************/ + [^] { + + final String errorMessage = "Analysis failure : Your file could not be analyzed. Please verify that it was encoded in an UNIX format."; + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } \ No newline at end of file diff --git a/fr.cnes.analysis.tools.fortran90.metrics/plugin.xml b/fr.cnes.analysis.tools.fortran90.metrics/plugin.xml index 4476e383..81b1aaab 100755 --- a/fr.cnes.analysis.tools.fortran90.metrics/plugin.xml +++ b/fr.cnes.analysis.tools.fortran90.metrics/plugin.xml @@ -34,5 +34,12 @@ languageId="fr.cnes.analysis.tools.languages.f90" name="F90.MET.RatioComment"> + + diff --git a/fr.cnes.analysis.tools.fortran90.metrics/pom.xml b/fr.cnes.analysis.tools.fortran90.metrics/pom.xml index 190a82ed..df895d71 100644 --- a/fr.cnes.analysis.tools.fortran90.metrics/pom.xml +++ b/fr.cnes.analysis.tools.fortran90.metrics/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran90.metrics diff --git a/fr.cnes.analysis.tools.fortran90.rules/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.fortran90.rules/META-INF/MANIFEST.MF index e3e0dda2..15dafc7e 100755 --- a/fr.cnes.analysis.tools.fortran90.rules/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.fortran90.rules/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES F90 Rules Bundle-SymbolicName: fr.cnes.analysis.tools.fortran90.rules;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.fortran90.rules.Activator Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0" diff --git a/fr.cnes.analysis.tools.fortran90.rules/pom.xml b/fr.cnes.analysis.tools.fortran90.rules/pom.xml index ec528c0e..cdcf9557 100644 --- a/fr.cnes.analysis.tools.fortran90.rules/pom.xml +++ b/fr.cnes.analysis.tools.fortran90.rules/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran90.rules diff --git a/fr.cnes.analysis.tools.languages/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.languages/META-INF/MANIFEST.MF index c237aef4..03ae68d4 100644 --- a/fr.cnes.analysis.tools.languages/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.languages/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Languages Bundle-SymbolicName: fr.cnes.analysis.tools.languages;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.languages.Activator Bundle-Vendor: CNES Require-Bundle: org.eclipse.core.runtime, diff --git a/fr.cnes.analysis.tools.languages/pom.xml b/fr.cnes.analysis.tools.languages/pom.xml index a7361c27..7d3f66c5 100644 --- a/fr.cnes.analysis.tools.languages/pom.xml +++ b/fr.cnes.analysis.tools.languages/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.languages diff --git a/fr.cnes.analysis.tools.shell.metrics/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.shell.metrics/META-INF/MANIFEST.MF index 0550c4d4..912228ab 100755 --- a/fr.cnes.analysis.tools.shell.metrics/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.shell.metrics/META-INF/MANIFEST.MF @@ -2,10 +2,11 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES SH Metrics Bundle-SymbolicName: fr.cnes.analysis.tools.shell.metrics;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.shell.metrics.Activator Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Vendor: CNES +Export-Package: fr.cnes.analysis.tools.shell.metrics diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfComment.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfComment.lex new file mode 100644 index 00000000..56a47b94 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfComment.lex @@ -0,0 +1,382 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ + +/********************************************************************************/ +/* This file is used to generate a metric checker for comment's rate. For */ +/* further information on this, we advise you to refer to CNES manual dealing */ +/* with metrics. */ +/* As many comments have been done on the MAXImbric.lex file, this file */ +/* will restrain its comments on modifications. */ +/* */ +/********************************************************************************/ + +package fr.cnes.analysis.tools.shell.metrics; + +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; + +import java.util.EmptyStackException; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +import java.util.logging.Logger; + +import org.eclipse.core.runtime.Path; + +%% + +%class SHMETLineOfComment +%extends AbstractChecker +%public +%column +%line + + +%function run +%yylexthrow JFlexException +%type List + +%state COMMENT, NAMING, BEGINFUNC, STRING, COMMAND + +COMMENT_WORD = [\#] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f\space] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) +IGNORE_COMMAND = \\` +COMMAND = \` +STRING_D = \" +IGNORE_STRING_D = \\\" +STRING_S = \' +IGNORE_STRING_S = \\\' +IGNORE = {IGNORE_STRING_D} | {IGNORE_STRING_S} | {IGNORE_COMMAND} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +%{ + private String location = "MAIN PROGRAM"; + private String parsedFileName; + private List identifiers = new LinkedList(); + private float lines=0; + private boolean emptyLine = true; + private boolean inStringSimpleQuoted = false; + private boolean inStringDoubleQuoted = false; + private float lastLinesCommented = 0; + private int functionLine; + private float commentLinesMain=0; + private float commentLinesTotal=0; + private float linesMain=0; + private float linesTotal=0; + private Stack functionStack = new Stack<>(); + private static final Logger LOGGER = Logger.getLogger(SHMETLineOfComment.class.getName()); + + public SHMETLineOfComment(){ + } + + @Override + public void setInputFile(File file) throws FileNotFoundException { + super.setInputFile(file); + LOGGER.fine("begin method setInputFile"); + this.parsedFileName = file.toString(); + this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); + LOGGER.fine("end method setInputFile"); + } + + private void endLocation() throws JFlexException { + LOGGER.fine("begin method endLocation"); + try{ + FunctionLineOfComment functionFinished = functionStack.pop(); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionFinished.getName()+" line :"+ functionFinished.getBeginLine()+" with value : "+(functionFinished.getLineOfComment()/functionFinished.getLineOfCode())*100); + this.computeMetric(functionFinished.getName(), functionFinished.getLineOfComment(), functionFinished.getBeginLine()); + + if(functionStack.empty()){ + linesMain+=functionFinished.getLineOfCode(); + commentLinesMain+=functionFinished.getLineOfComment(); + }else{ + FunctionLineOfComment function = functionStack.peek(); + function.setLineOfCode(function.getLineOfCode()+functionFinished.getLineOfCode()); + function.setLineOfComment(function.getLineOfComment()+functionFinished.getLineOfComment()); + } + }catch(EmptyStackException e){ + + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + LOGGER.fine("end method setInputFile"); + } + + private void addLines(){ + LOGGER.fine("begin method addLines"); + if(!emptyLine){ + if(functionStack.empty()){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to MAIN PROGRAM"); + linesMain++; + } else { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to the function "+ functionStack.peek().getName()); + functionStack.peek().addLineOfCode(); + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line for the whole file"); + linesTotal++; + } + LOGGER.fine("end method addLines"); + } + private void addCommentLines(){ + LOGGER.fine("begin method addCommentLines"); + if(functionStack.empty()){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one comment line to MAIN PROGRAM"); + commentLinesMain++; + } else { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one comment line to the function "+ functionStack.peek().getName()); + functionStack.peek().addLineOfComment(); + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one comment line for the whole file"); + commentLinesTotal++; + LOGGER.fine("end method addLines"); + } + +%} + +%eofval{ + if(functionStack.empty()){ + this.computeMetric("MAIN PROGRAM", commentLinesMain, 1); + }else{ + + final String errorMessage = "Analysis failure : At least one function is not ending correctly."; + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + this.computeMetric(null, commentLinesTotal, 0); + + return getCheckResults(); +%eofval} +%% + +/************************/ +/* COMMENT STATE */ +/************************/ + + { + \n { + lastLinesCommented++; + //Count pending the value of emptyline (as the comment might be on the right side of some code) + addLines(); + addCommentLines(); + emptyLine=true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } + } + +/************************/ +/* YYINITIAL STATE */ +/************************/ + + { + + + {COMMENT_WORD} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + yybegin(COMMENT); + } + {FUNCTION} { + emptyLine = false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + yybegin(NAMING); + } + {FUNCT} { + emptyLine = false; + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + + {FUNCSTART} { + emptyLine = false; + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addStarterRepetition(); + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for FUNCSTART \""+yytext()+"\" )"); + } + } + {FUNCEND} { + lastLinesCommented=0; + emptyLine = false; + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + try{ + functionStack.peek().removeStarterRepetition(); + }catch(JFlexException e){ + + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } else { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + addLines(); + emptyLine=true; + endLocation(); + } + } + } + } + {VAR} { + lastLinesCommented=0; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for VAR \""+yytext()+"\" )"); + emptyLine = false; + } + {IGNORE} { + lastLinesCommented=0; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + emptyLine = false; + } + {COMMAND} { + lastLinesCommented=0; + emptyLine = false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(COMMAND); + } + {STRING_S} { + lastLinesCommented=0; + emptyLine = false; + inStringSimpleQuoted = true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING); + } + {STRING_D} { + lastLinesCommented=0; + emptyLine = false; + inStringDoubleQuoted = true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING); + } + + \n { + lastLinesCommented=0; + addLines(); + emptyLine=true; + } + {SPACE} { } + . { + lastLinesCommented=0; + emptyLine = false; + } + } + + +/************************/ +/* NAMING STATE */ +/************************/ + + { + {VAR} { + emptyLine = false; + location = yytext(); + functionLine = yyline+1; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + \n { + addLines(); + emptyLine = true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} {} + } + +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + FunctionLineOfComment function = new FunctionLineOfComment(location, functionLine, yytext()); + if(lastLinesCommented>0){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] Transfering "+ lastLinesCommented +" lines detected as header comment from the last function to the new one. )"); + if(functionStack.empty()){ + commentLinesMain-=lastLinesCommented; + }else{ + functionStack.peek().setLineOfComment(functionStack.peek().getLineOfComment() - lastLinesCommented); + } + function.setLineOfComment(lastLinesCommented); + lastLinesCommented = 0; + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + functionStack.push(function); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } +/************************/ +/* COMMAND STATE */ +/************************/ + + { + \n { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] count line for \\n"); + addLines(); + } + {COMMAND} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } + } +/************************/ +/* STRING STATE */ +/************************/ + + { + \n { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] count line for \\n"); + addLines(); + } + {IGNORE} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_S} { + if(inStringSimpleQuoted){ + inStringSimpleQuoted=false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + + } + {STRING_D} { + if(inStringDoubleQuoted){ + inStringDoubleQuoted=false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + + } + . | {SPACE} { } + } diff --git a/fr.cnes.analysis.tools.shell.metrics/plugin.xml b/fr.cnes.analysis.tools.shell.metrics/plugin.xml index 4fc59342..65bf6fb5 100755 --- a/fr.cnes.analysis.tools.shell.metrics/plugin.xml +++ b/fr.cnes.analysis.tools.shell.metrics/plugin.xml @@ -34,5 +34,12 @@ languageId="fr.cnes.analysis.tools.languages.shell" name="SH.MET.RatioComment"> + + diff --git a/fr.cnes.analysis.tools.shell.metrics/pom.xml b/fr.cnes.analysis.tools.shell.metrics/pom.xml index a4d6abb1..8cec3668 100644 --- a/fr.cnes.analysis.tools.shell.metrics/pom.xml +++ b/fr.cnes.analysis.tools.shell.metrics/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.shell.metrics diff --git a/fr.cnes.analysis.tools.shell.rules/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.shell.rules/META-INF/MANIFEST.MF index 38a53b37..a3f84637 100755 --- a/fr.cnes.analysis.tools.shell.rules/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.shell.rules/META-INF/MANIFEST.MF @@ -2,10 +2,11 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES SH Rules Bundle-SymbolicName: fr.cnes.analysis.tools.shell.rules;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.shell.rules.Activator Require-Bundle: org.eclipse.core.runtime, - fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0" + fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0", + fr.cnes.analysis.tools.shell.metrics;bundle-version="3.1.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Vendor: CNES diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInitialisation.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInitialisation.lex index e386fc18..399fa110 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInitialisation.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInitialisation.lex @@ -20,12 +20,15 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -40,12 +43,24 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, WRITE, STRING, FORLOOP, READ +%state COMMENT, NAMING, WRITE, STRING, FORLOOP, READ, BEGINFUNC COMMENT_WORD = \# -FUNC = "function" -SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SPACE = [\ \r\t\f] +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) + +FOR = "for" + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + + FILEEXIST = \[{SPACE}+{OPTION}{SPACE}+(\")?(\{)?\$(\{)?{VAR}(\})?(\")? OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | "p" | "r" | "s" | "u" | "w" | "x" | "O" | "G" | "L" | @@ -53,8 +68,21 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | %{ - String location = "MAIN PROGRAM"; - List variables = new ArrayList(); + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + /* FunctionWithVariables is used here with only initialized variables in locals and glabals */ + private Stack functionStack = new Stack<>(); + + /* location: the current function name, or main program, that is the initial value */ + private String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + + /* parsedFileName: name of the current file */ + private String parsedFileName; + + List globalVariables = new ArrayList(); public COMDATAInitialisation() { /** Initialize list with system variables **/ @@ -64,15 +92,80 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | "MACHTYPE", "OLDPWD", "OSTYPE", "PATH", "PIPESTATUS", "PPID", "PROMPT_COMMAND", "PS1", "PS2", "PS3", "PS4", "PWD", "REPLY", "SECONDS", "SHELLOPTS", "SHLVL", "TMOUT", "UID" }; - variables.addAll(Arrays.asList(systemVariables)); + globalVariables.addAll(Arrays.asList(systemVariables)); } @Override public void setInputFile(final File file) throws FileNotFoundException { super.setInputFile(file); + this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + + /** + * checkVariable: checks for violations on the current variable name (var). + * Called from YYINITIAL and STRING. + */ + private void checkVariable(final String var) throws JFlexException { + boolean found = false; + if(!functionStack.empty()){ + /* we are in a function */ + if (functionStack.peek().getLocalVariables().contains(var)) + found = true; + if (functionStack.peek().getGlobalVariables().contains(var)) + found = true; + } + if(!found && !globalVariables.contains(var)) { + setError(location,"The variable $" + var + " is used before being initialized." , yyline+1); + } + } + + /** + * addVariable: adds the current variable name (var) to the list of variables : glabals if + * in main, locals if in funtion. + * Called from YYINITIAL, WRITE, FORLOOP and READ. + */ + private void addVariable(final String var) throws JFlexException { + if(!functionStack.empty()){ + /* we are in a function */ + functionStack.peek().getLocalVariables().add(var); + } else { + /* we are in main */ + globalVariables.add(var); + } + } + + /** + * setGlobals: adds the current globals to the globals of pFunction. + * If there is a higher level function, its locals are also added. + * Called from BEGINFUNC. + */ + private void setGlobals(FunctionWithVariables pFunction) throws JFlexException { + if(!functionStack.empty()){ + /* we are in a function: add the locals of the current function as globals of the new function */ + pFunction.getGlobalVariables().addAll(functionStack.peek().getLocalVariables()); + } + /* in all cases add the current globals */ + pFunction.getGlobalVariables().addAll(globalVariables); + } + %} %eofval{ @@ -102,9 +195,15 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | /************************/ { - {VAR} {location = location + yytext(); yybegin(YYINITIAL);} - \n {yybegin(YYINITIAL);} - . {} + {FNAME} { + location = yytext(); + functionLine = yyline+1; + yybegin(BEGINFUNC); + } + \n { + yybegin(YYINITIAL); + } + . {} } /************************/ @@ -113,18 +212,48 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | { {COMMENT_WORD} {yybegin(COMMENT);} - {FUNC} {location = yytext(); yybegin(NAMING);} - /** variables initialisation **/ + {FUNCTION} {yybegin(NAMING);} + {FUNCT} { + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC); + } + {FOR} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + yybegin(FORLOOP); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + /** variables initialisation **/ {VAR}{SPACE}*\= {String var = yytext().substring(0,yytext().length()-1).trim(); - variables.add(var);} + addVariable(var);} /** Varible use found **/ \${VAR} {String var = yytext().substring(1); - if(!variables.contains(var)) setError(location,"The variable $" + var + " is used before being initialized." , yyline+1);} + checkVariable(var);} "tee" | \>\> {yybegin(WRITE);} - "for" {yybegin(FORLOOP);} "read" {yybegin(READ);} {FILEEXIST} {String var = yytext().replaceAll("\"", "").replaceAll("\\{", "").replaceAll("\\}", "").split("\\$")[1]; - variables.add(var);} + addVariable(var);} {VAR} {} \" {yybegin(STRING);} . {} @@ -137,7 +266,7 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | { \-{VAR} {} \$(\{)?{VAR} {String var = yytext().substring(1).replace("{",""); - variables.add(var);} + addVariable(var);} \n | \; {yybegin(YYINITIAL);} . {} } @@ -147,7 +276,7 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | /************************/ { - {VAR} {variables.add(yytext()); yybegin(YYINITIAL);} + {VAR} {addVariable(yytext()); yybegin(YYINITIAL);} \n | \; {yybegin(YYINITIAL);} . {} } @@ -159,7 +288,7 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | { \\\$ {} \$(\{)?{VAR} {String var = yytext().substring(1).replace("{",""); - if(!variables.contains(var)) setError(location,"The variable $" + var + " is used before being initialized." , yyline+1);} + checkVariable(var);} \n | \; | \" {yybegin(YYINITIAL);} . {} } @@ -169,11 +298,39 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | /************************/ { - {VAR} {variables.add(yytext()); } + {VAR} {addVariable(yytext()); } \n | \; {yybegin(YYINITIAL);} . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FOR} { + FunctionWithVariables function; + function = new FunctionWithVariables(location, functionLine, yytext()); + setGlobals(function); + functionStack.push(function); + yybegin(FORLOOP); + } + {FUNCSTART} { + FunctionWithVariables function; + function = new FunctionWithVariables(location, functionLine, yytext()); + setGlobals(function); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInvariant.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInvariant.lex index de0908f0..8a49e70a 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInvariant.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMDATAInvariant.lex @@ -21,12 +21,15 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -41,12 +44,16 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, INVARIANT, AVOID +%state COMMENT, NAMING, INVARIANT, AVOID, BEGINFUNC, AWK, AWK_STRING, STRING_SIMPLE, STRING_DOUBLE, FOR COMMENT_WORD = \# -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FOR = "for" +DONE = "done" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SPACE = [\ \r\t\f]* VAR = [a-zA-Z][a-zA-Z0-9\_]* EXTENSION = (\.{VAR})+ SEPAR = [\ ] | \+ | \- | \* | \/ @@ -68,7 +75,18 @@ OPER = "++" | "--" IGNORE = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | "typeset" | "declare" | "--"[a-zA-Z\-]*"=" -CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk" | +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +AWK = "awk" +COMMAND_END = [\n;] + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] + +CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "basename" | "bash" | "bc" | "bg" | "break" | "builtin" | "bzip2" | "cal" | "case" | "cd" | "cfdisk" | "chgrp" | "chmod" | "chown" | "chroot" | "chkconfig" | "cksum" | "clear" | "cmp" | "comm" | "command" | @@ -111,7 +129,7 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk private String parsedFileName; private String location = MAINPROGRAM; /* VARIABLE: constant for variable error message */ - private static final String VARIABLE = " -> The variable "; + private static final String VARIABLE = "The variable "; /* DECLARE_CONST: message for constant error message */ private static final String DECLARE_CONST = " should be declared constant"; /* errVariables: contains all variables that for the moment should be consts */ @@ -124,23 +142,34 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk /* int: variable line in code, String: location in code (function name) */ private final Map varLocations = new HashMap(); - /* localErrVariables: contains all current function local variables that for the moment */ - /* should be consts */ - /* String: variable name, Integer: variable line in code */ - private final Map localErrVariables = new HashMap(); - /* localOkVariables: contains all current function variables that have either been declared as */ - /* consts or should be variables. There should be no violation on them. */ - private final List localOkVariables = new ArrayList(); - + List globalVariables = new ArrayList(); private boolean variableError = false; private boolean invariantError = false; private boolean separator = false; private String variable = ""; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + + /* The global variables in the class will be used to stock the okVariables of the function */ + private Stack functionStack = new Stack<>(); + /* addVar: method that adds the just initialised variable var to the correct list according to its status */ - private void addVar(final String var) { + private void addVar(final String var) { + if(!functionStack.empty()){ + /* we are in a function: add the variable to the correct list in the function */ + functionAddVar(var); + } else { + /* we are in main */ + mainAdd(var); + } + } + + /* mainAdd: method that adds the just initialised variable var to the correct list according to its status */ + /* we are in main */ + private void mainAdd(final String var) { final Boolean found = errVariables.containsKey(var); if (found) { /* var is in errVariables, this is the 2nd initialisation */ @@ -152,36 +181,77 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk /* this is its 1st initialisation */ errVariables.put(var, yyline); varLocations.put(yyline, location); + globalVariables.add(var); } } + + /* functionAddVar: method that adds the just initialised variable var to the correct list according to its status */ + /* we are in a function */ + private void functionAddVar(final String var) { + FunctionInvariant function = functionStack.peek(); + HashMap functionErrVariables = function.getErrVariables(); + final Boolean found = functionErrVariables.containsKey(var); + List functionOkVariables = function.getOkVariables(); + List functionGlobals = function.getGlobalVariables(); + List functionOkGlobalVariables = function.getOkGlobalVariables(); + + if (found) { + /* var is in function ErrVariables, this is the 2nd initialisation */ + /* var doesn't need to be const */ + functionErrVariables.remove(var); + functionOkVariables.add(var); + } else if (!functionOkVariables.contains(var)) { + /* var isn't in the already initiated local variables in any way */ + /* this is its 1st initialisation */ + if (!functionGlobals.contains(var)) + { + /* the variable is not global: that means it is really a 1st local initialisation */ + function.getLocalVariables().add(var); + functionErrVariables.put(var, yyline); + } else { + /* the variable is global for the function, meaning that this is its 2nd initialisation */ + /* the functionOkVariables will be passed up to the containing function or main */ + functionOkVariables.add(var); + functionOkGlobalVariables.add(var); + } + } + } + /* localAddVar: method that adds the just initialised local variable var to the correct list according to its status */ - private void localAddVar(final String var) { - final Boolean found = localErrVariables.containsKey(var); - if (found) { - /* var is in localErrVariables, this is the 2nd initialisation */ + /* always called in the case of a local variable */ + private void localAddVar(final String var, Boolean localReadOnly) { + FunctionInvariant function = functionStack.peek(); + HashMap functionErrVariables = function.getErrVariables(); + final Boolean found = functionErrVariables.containsKey(var); + List functionOkVariables = function.getOkVariables(); + + if (localReadOnly) { + functionOkVariables.add(var); + function.getLocalVariables().add(var); + } else if (found) { + /* var is in function ErrVariables, this is the 2nd initialisation */ /* var doesn't need to be const */ - localErrVariables.remove(var); - localOkVariables.add(var); - } else if (!localOkVariables.contains(var)) { + functionErrVariables.remove(var); + functionOkVariables.add(var); + } else if (!functionOkVariables.contains(var)) { /* var isn't in the already initiated variables in any way */ /* this is its 1st initialisation */ - localErrVariables.put(var, yyline); - } + function.getLocalVariables().add(var); + functionErrVariables.put(var, yyline); + } } - - /* addViolationLocation: adds the list of violations on variables of the just ended function (location) */ - private void addViolationsLocation() throws JFlexException { - for (final Map.Entry entry : localErrVariables.entrySet()) { + /* addViolationLocation: adds the list of violations on variables of the just ended function (location) */ + /* Called at the end of a function */ + private void addViolationsLocation(HashMap functionErrVariables) throws JFlexException { + for (final Map.Entry entry : functionErrVariables.entrySet()) { final String var = entry.getKey(); final Integer line = entry.getValue(); /* location is current location */ + setError(location, VARIABLE + var + DECLARE_CONST, line+1); } - /* Clear the local tables ready for the next function */ - localErrVariables.clear(); - localOkVariables.clear(); } public COMDATAInvariant() { @@ -194,7 +264,48 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + FunctionInvariant functionFinished = functionStack.pop(); + addViolationsLocation(functionFinished.getErrVariables()); + /* list of son function's locals, that also contain relative global OKs */ + /* Remove those that were locals first */ + ArrayList sonOkVariables = functionFinished.getOkGlobalVariables(); + if (!functionStack.empty()) { + /* there is a current function */ + FunctionInvariant currentFunction = functionStack.peek(); + currentFunction.addSonOkVariables(sonOkVariables); + location = currentFunction.getName(); + } else { + /* we are in the main program */ + for (String var : sonOkVariables) { + errVariables.remove(var); + okVariables.add(var); + } + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + + /** + * setGlobals: adds the current globals to the globals of pFunction. + * If there is a higher level function, its locals are also added. + */ + private void setGlobals(FunctionWithVariables pFunction) throws JFlexException { + if(!functionStack.empty()){ + /* we are in a function: add the locals of the current function as globals of the new function */ + pFunction.getGlobalVariables().addAll(functionStack.peek().getGlobalVariables()); + pFunction.getGlobalVariables().addAll(functionStack.peek().getLocalVariables()); + } else { + pFunction.getGlobalVariables().addAll(globalVariables); + } + } + %} %eofval{ @@ -240,7 +351,7 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {VAR} {location = yytext(); yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -251,8 +362,36 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk { {COMMENT_WORD} {yybegin(COMMENT);} - {FUNCTION} {if (! location.equals(MAINPROGRAM)) addViolationsLocation(); yybegin(NAMING);} - {FUNCT} {if (! location.equals(MAINPROGRAM)) addViolationsLocation(); location = yytext().substring(0,yytext().length()-2).trim();} + {AWK} {yybegin(AWK);} + {FOR}{SPACE}*\(\( { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + yybegin(FOR); + } + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC);} + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } /** variables intialisation -> new sate to check rule **/ {CLE}{SPACE}+ {yybegin(AVOID);} {IGNORE} {} @@ -264,13 +403,15 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk {SPACE}{1}{VAR}{OPER} {addVar(yytext().substring(1, yytext().length()-2)); yybegin(INVARIANT);} {OPER}{VAR}{SPACE}{1} {addVar(yytext().substring(2, yytext().length()-1)); yybegin(INVARIANT);} {VAR}"+=" {addVar(yytext().substring(0, yytext().length()-2)); yybegin(INVARIANT);} - {LOCALREADONLY}{VAR}\= {int varPos = yytext().lastIndexOf(' '); + {LOCALREADONLY}{SPACE}{VAR}\= { + int varPos = yytext().lastIndexOf(' ') + 1; String var = yytext().substring(varPos, yytext().length()-1); - localOkVariables.add(var); + localAddVar(var, true); yybegin(INVARIANT);} - {LOCAL}{VAR}\= {int varPos = yytext().lastIndexOf(' '); + {LOCAL}{SPACE}{VAR}\= { + int varPos = yytext().lastIndexOf(' ') + 1; String var = yytext().substring(varPos, yytext().length()-1); - localAddVar(var); + localAddVar(var, false); yybegin(INVARIANT);} [^] {} } @@ -294,6 +435,98 @@ CLE = "alias" | "apropos" | "apt-get" | "aptitude" | "ascp" | "aspell" | "awk . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FOR}{SPACE}*\(\( { + FunctionInvariant function; + function = new FunctionInvariant(location, functionLine, yytext()); + setGlobals(function); + functionStack.push(function); + yybegin(FOR); + } + {FUNCSTART} { + FunctionInvariant function; + function = new FunctionInvariant(location, functionLine, yytext()); + setGlobals(function); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } +/* + * The AWK states are designed to ignore awk commands + */ +/************************/ +/* AWK STATE */ +/************************/ + + { + {STRING_S} {yybegin(AWK_STRING);} + {COMMAND_END} {yybegin(YYINITIAL);} + . {} + } + +/************************/ +/* AWK_STRING STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(AWK);} + [^]|{SPACE} {} + } + +/************************/ +/* FOR STATE */ +/************************/ + + { + {DONE} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + yybegin(YYINITIAL); + } + . {} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMDATALoopCondition.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMDATALoopCondition.lex index 9edbd4ca..2493d6dc 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMDATALoopCondition.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMDATALoopCondition.lex @@ -19,12 +19,15 @@ import java.io.FileReader; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -40,23 +43,42 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, WHILE, FOR +%state COMMENT, NAMING, WHILE, FOR, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# -FUNC = "function" +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" -WHILE = "while" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] + +WHILE = "while" | "until" FOR = "for" DONE = "done" +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; List> conditions = new ArrayList>(); List variables = new ArrayList(); + private Stack functionStack = new Stack<>(); + public COMDATALoopCondition() { } @@ -90,7 +112,24 @@ DONE = "done" } } } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + %} %eofval{ @@ -120,7 +159,7 @@ DONE = "done" /************************/ { - {VAR} {location = location + yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -131,12 +170,60 @@ DONE = "done" { {COMMENT_WORD} {yybegin(COMMENT);} - {STRING} {} - {FUNC} {location = yytext(); yybegin(NAMING);} - {WHILE} {yybegin(WHILE);} - {FOR} {yybegin(FOR);} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC);} + {WHILE} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + yybegin(WHILE); + } + {FOR} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + yybegin(FOR); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } {VAR}\= {String var = yytext().substring(0, yytext().length()-1); checkVariable(var);} - {DONE} {int index = conditions.size() - 1; if (index >= 0) {conditions.remove(index);}} + {DONE} { + int index = conditions.size() - 1; + if (index >= 0) {conditions.remove(index);} + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } {VAR} {} [^] {} } @@ -168,6 +255,62 @@ DONE = "done" . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {WHILE} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(WHILE); + } + {FOR} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(FOR); + } + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMDATANotUsed.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMDATANotUsed.lex index bc48fd67..6f9a30c3 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMDATANotUsed.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMDATANotUsed.lex @@ -44,7 +44,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* @@ -123,7 +124,7 @@ VAR = [a-zA-Z][a-zA-Z0-9\_]* /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMDESIGNActiveWait.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMDESIGNActiveWait.lex index 6b5c02c9..5f6892f7 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMDESIGNActiveWait.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMDESIGNActiveWait.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,21 +42,38 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING +%state COMMENT, NAMING, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# -FUNC = "function" -SPACE = [\ \r\t\f] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" -ACTWAIT = "while"{SPACE}*\[{SPACE}*"1"{SPACE}*\]{SPACE}* | - "read" +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] + +ACTWAIT_WHILE = "while"{SPACE}*\[{SPACE}*"1"{SPACE}*\]{SPACE}* +ACTWAIT = "read" | "sleep" | "wait" %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; + private Stack functionStack = new Stack<>(); + public COMDESIGNActiveWait() { } @@ -64,7 +84,24 @@ ACTWAIT = "while"{SPACE}*\[{SPACE}*"1"{SPACE}*\]{SPACE}* | this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + %} %eofval{ @@ -94,7 +131,7 @@ ACTWAIT = "while"{SPACE}*\[{SPACE}*"1"{SPACE}*\]{SPACE}* | /************************/ { - {VAR} {location = location + yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -105,13 +142,93 @@ ACTWAIT = "while"{SPACE}*\[{SPACE}*"1"{SPACE}*\]{SPACE}* | { {COMMENT_WORD} {yybegin(COMMENT);} - {FUNC} {location = yytext(); yybegin(NAMING);} - {ACTWAIT} {setError(location,"There is an active wait in this point.", yyline+1); } - {STRING} {} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC);} + {ACTWAIT} {setError(location,"There is an active wait in this point.", yyline+1); } + {ACTWAIT_WHILE} { + setError(location,"There is an active wait in this point.", yyline+1); + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } {VAR} {} /* Clause to match with words */ [^] {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {ACTWAIT_WHILE} { + setError(location,"There is an active wait in this point.", yyline+1); + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWAbort.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWAbort.lex index a2c8e114..f3a43c23 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWAbort.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWAbort.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,22 +42,40 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, KILL +%state COMMENT, NAMING, KILL, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# -FUNC = "function" +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] VAR = (\$)?[a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] ABORT = ("kill"|"pkill"|"killall") OPTIONS = \- ("9" | "SIGKILL" | "kill") %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; String errorKill = ""; + private Stack functionStack = new Stack<>(); + public COMFLOWAbort() { } @@ -65,7 +86,23 @@ OPTIONS = \- ("9" | "SIGKILL" | "kill") this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} %eofval{ @@ -95,7 +132,7 @@ OPTIONS = \- ("9" | "SIGKILL" | "kill") /************************/ { - {VAR} {location = location + yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -106,9 +143,31 @@ OPTIONS = \- ("9" | "SIGKILL" | "kill") { {COMMENT_WORD} {yybegin(COMMENT);} - {FUNC} {location = yytext(); yybegin(NAMING);} + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC);} + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } {ABORT} {errorKill= yytext(); yybegin(KILL);} - {STRING} {} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} {VAR} {} /* Clause to match with words that contains "kill" */ [^] {} } @@ -125,6 +184,48 @@ OPTIONS = \- ("9" | "SIGKILL" | "kill") . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWBooleanExpression.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWBooleanExpression.lex index 6e7edc1c..4f655358 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWBooleanExpression.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWBooleanExpression.lex @@ -42,8 +42,9 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %state COMMENT, NAMING, CONDITIONAL, LOOP COMMENT_WORD = \# -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCTION = "function" +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -99,7 +100,7 @@ BOOL = \|\| | \&\& | \-"o" | \-"a" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWCaseSwitch.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWCaseSwitch.lex index 5705cbb1..07ab2b48 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWCaseSwitch.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWCaseSwitch.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,20 +42,39 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, CONDITIONAL +%state COMMENT, NAMING, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# -FUNC = "function" +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] CASE = "case" ESAC = "esac" %{ - String location = "MAIN PROGRAM"; - private String parsedFileName; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + + private String parsedFileName; boolean defaultExpr = false; + + private Stack functionStack = new Stack<>(); + public COMFLOWCaseSwitch() { } @@ -64,7 +86,24 @@ ESAC = "esac" this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + %} %eofval{ @@ -94,7 +133,7 @@ ESAC = "esac" /************************/ { - {VAR} {location = location + yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -105,24 +144,106 @@ ESAC = "esac" { {COMMENT_WORD} {yybegin(COMMENT);} - {FUNC} {location = yytext(); yybegin(NAMING);} - {STRING} {} - {CASE} {defaultExpr=false; yybegin(CONDITIONAL);} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC);} + {CASE} { + defaultExpr=false; + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {ESAC} { + if(!defaultExpr) setError(location,"The default case of the case switch condition is missing.", yyline+1); + defaultExpr=false; + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + \*\) {defaultExpr=true;} {VAR} {} /* Clause to match with words that contains "kill" */ [^] {} } /************************/ -/* CONDITIONAL STATE */ +/* BEGINFUNC STATE */ /************************/ - +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + { - \*\) {defaultExpr=true;} - {ESAC} {if(!defaultExpr) setError(location,"The default case of the case switch condition is missing.", yyline+1); yybegin(YYINITIAL);} - {VAR} {} - [^] {} + \(\) {} + {CASE} { + defaultExpr=false; + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} } - + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExit.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExit.lex index 5300831d..a6a732d4 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExit.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExit.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -97,7 +98,7 @@ RETURN = "return" /************************/ { - {VAR} {location = yytext(); returns=0; brackets=0; yybegin(FUNCTION);} + {FNAME} {location = yytext(); returns=0; brackets=0; yybegin(FUNCTION);} \n {returns=0; yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExitLoop.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExitLoop.lex index 2ebdfae3..70dc77ba 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExitLoop.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWExitLoop.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -102,7 +103,7 @@ BREAK = "break" | "exit" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFileExistence.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFileExistence.lex index b9f800ae..94325018 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFileExistence.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFileExistence.lex @@ -25,6 +25,9 @@ import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import java.util.EmptyStackException; +import java.util.Stack; +import fr.cnes.analysis.tools.shell.metrics.Function; import java.util.logging.Logger; @@ -42,7 +45,7 @@ import java.util.logging.Logger; %type List -%state COMMENT, NAMING, FILE, STRING +%state COMMENT, NAMING, FILE, STRING, BEGINFUNC COMMENT_WORD = [\#] FUNCTION = "function" @@ -54,6 +57,8 @@ SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) EXPANDED_VAR = [\!]?{NAME}([\:]|(([\%]?[\%])|([\#]?[\#]))|([\:]?[\=\+\?\-]))({NAME}|[\[]{NAME}[\]])|([\#]{NAME}) VAR = ({NAME}|([\$][\{]({NAME}|{SHELL_VAR}|{EXPANDED_VAR})[\}])|([\$]({NAME}|{SHELL_VAR}))) +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" OPERATOR_RIGHT = [\>]|[\>][\&]|[\&][\>]|[\>][\>]|[\>][\>][\>] OPERATOR_LEFT = [\<]|[\<][\&]|[\&][\<]|[\<][\<]|[\<][\<][\<] @@ -92,10 +97,18 @@ IGNORE = {REDIRECT_IGNORE} | {STRING_ESCAPED} | ([\\][\#]) | "ssh" %{ private static final Logger LOGGER = Logger.getLogger(COMFLOWFileExistence.class.getName()); - private String location = "MAIN PROGRAM"; - private String parsedFileName; - + + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + + private String parsedFileName; + private Stack functionStack = new Stack<>(); + List filesExistence = new ArrayList(); private String stringBeginner = ""; @@ -116,6 +129,23 @@ IGNORE = {REDIRECT_IGNORE} | {STRING_ESCAPED} | ([\\][\#]) | "ssh" this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); LOGGER.fine("end method setInputFile"); } + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} @@ -145,9 +175,10 @@ IGNORE = {REDIRECT_IGNORE} | {STRING_ESCAPED} | ([\\][\#]) | "ssh" /************************/ { - {VAR} {location = yytext(); + {FNAME} {location = yytext(); + functionLine = yyline+1; LOGGER.fine("["+this.parsedFileName+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : VAR \""+yytext()+"\" )"); - yybegin(YYINITIAL);} + yybegin(BEGINFUNC);} \n { LOGGER.fine("["+this.parsedFileName+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); yybegin(YYINITIAL);} @@ -165,8 +196,28 @@ IGNORE = {REDIRECT_IGNORE} | {STRING_ESCAPED} | ([\\][\#]) | "ssh" yybegin(NAMING); } {FUNCT} { + functionLine = yyline+1; location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC); } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } {FILEEXIST} { int index = yytext().indexOf('-'); String subfile = yytext().substring(index); @@ -266,7 +317,28 @@ IGNORE = {REDIRECT_IGNORE} | {STRING_ESCAPED} | ([\\][\#]) | "ssh" } . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state's target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFilePath.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFilePath.lex index b499c906..307337ad 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFilePath.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWFilePath.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,21 +42,68 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, INITIALISATION +%state COMMENT, NAMING, FILE, STRING, BEGINFUNC COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* +NAME = ([a-zA-Z\_][a-zA-Z0-9\_]*) +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\!]?{NAME}([\:]|(([\%]?[\%])|([\#]?[\#]))|([\:]?[\=\+\?\-]))({NAME}|[\[]{NAME}[\]])|([\#]{NAME}) +VAR = ({NAME}|([\$][\{]({NAME}|{SHELL_VAR}|{EXPANDED_VAR})[\}])|([\$]({NAME}|{SHELL_VAR}))) -POSERROR = {VAR}\= | \> | "cat" | "rm" | "more" -FILEEXT = \.[a-zA-Z][^\.]{0,5} - +STRING = [\"]|[\'] +ESCAPE = [\\] +FILE_SEPARATOR = [\/]|[\\] + +FILECHAR = [a-zA-Z0-9\_\.\?\!\^\+\*\-\%\ยง] +FILEWORD = (([\.]?{FILE_SEPARATOR})|([\~]))?(({FILECHAR}+|{VAR}){FILE_SEPARATOR}?)+ +FILESTRING = (([\"]{SPACE}*{FILEWORD}{SPACE}*[\"])|([\']{SPACE}*{FILEWORD}{SPACE}*[\'])|{FILEWORD})+ + +FILEEXIST = "test" (\!)? {SPACE}+ {OPTION}{SPACE}+{FILESTRING}+ | \[ {SPACE}* (\!)? {SPACE}+ {OPTION}{SPACE}+{FILESTRING}+ {SPACE}+ \] + +OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" | + "p" | "r" | "s" | "u" | "w" | "x" | "O" | "G" | "L" | + "N" | "S") + +COMMAND_END = [\n] | [\;] | [\|] | [\`] +COMMAND_NAME = "cat" | "tee" | "more" | "less" | "head" | "wc" | "sh" | "rm" +GREP_COMMAND = "grep"{SPACE}+(([\-][AB]{SPACE}+[0-9]+{SPACE}+)?|([\-]?[\-][a-zC-Z]+{SPACE}+)?)*([\-][\e]{SPACE}+)?[\^]?(([\"]([^\"]|([\\][\"]))*[\"])|([\']([^\']|([\\][\']))*[\'])|({FNAME}+|{VAR})+) +BASE_COMMAND = {COMMAND_NAME}{SPACE}+([\-]?[\-]({VAR}|{FNAME})+([\=]({VAR}|{FNAME})+)?{SPACE}*)*{SPACE}* +ASSIGN = {VAR}\={SPACE}*([\-]?[\-]({VAR}|{FNAME})+([\=]({VAR}|{FNAME})+)?{SPACE}*)*{SPACE}* +FILE_COMMAND = {GREP_COMMAND} | {BASE_COMMAND} | {ASSIGN} + +OPERATOR_RIGHT = [\>]|[\>][\&]|[\&][\>]|[\>][\>]|[\>][\>][\>] +OPERATOR_LEFT = [\<]|[\<][\&]|[\&][\<]|[\<][\<]|[\<][\<][\<] +OPERATOR_RL = [\<][\>] +RIGHT_FILE_REDIRECT = ({OPERATOR_RIGHT}|{OPERATOR_RL}){SPACE}*{FILESTRING} +LEFT_FILE_REDIRECT = {FILESTRING}{SPACE}*({OPERATOR_LEFT}|{OPERATOR_RL}) +REDIRECT_IGNORE = ([0-2]({OPERATOR_LEFT}|{OPERATOR_RL})) | (({OPERATOR_RIGHT}|{OPERATOR_RL})[0-2]) + +STRING_ESCAPED = [\\]{STRING} +IGNORE = {REDIRECT_IGNORE} | {STRING_ESCAPED} | ([\\][\#]) | "ssh" + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; + private String stringBeginner = ""; + private boolean escapeNext = false; + + private Stack functionStack = new Stack<>(); + + public COMFLOWFilePath() { } @@ -64,7 +114,24 @@ FILEEXT = \.[a-zA-Z][^\.]{0,5} this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + %} %eofval{ @@ -94,7 +161,7 @@ FILEEXT = \.[a-zA-Z][^\.]{0,5} /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -104,24 +171,116 @@ FILEEXT = \.[a-zA-Z][^\.]{0,5} /************************/ { - {COMMENT_WORD} {yybegin(COMMENT);} + {COMMENT_WORD} {if (!escapeNext) {yybegin(COMMENT);}} {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim();} - {POSERROR} {yybegin(INITIALISATION);} - {VAR} {} /* Clause to match with words */ - [^] {} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {IGNORE} {} + {FILEEXIST} { + int index = yytext().indexOf('-'); + String subfile = yytext().substring(index); + String name = subfile.replaceAll("\"", "").replaceAll("\\{", "").replaceAll("\\}", "").replaceAll("]", "").split(" ")[1]; + setError(location,"It is forbidden to use a file name such as " + name + " directly.", yyline+1); + } + {LEFT_FILE_REDIRECT}|{RIGHT_FILE_REDIRECT} + { + String name = yytext().replaceAll("([\\s]|[\\>]|[\\\"]|[\\']|[\\<]|[\\&]|[\\{]|[\\}])+",""); + setError(location,"It is forbidden to use a file name such as " + name + " directly.", yyline+1); + } + {FILE_COMMAND} {yybegin(FILE);} + {STRING} { + stringBeginner=yytext(); + yybegin(STRING); + } + [^] {} } /************************/ -/* INITIALISATION STATE */ +/* FILE STATE */ /************************/ - + { - {FILEEXT} {setError(location,"It is not allowed to specify the file with this name. Use a variable instead.", yyline+1); yybegin(YYINITIAL);} - \n | \; {yybegin(YYINITIAL);} - . {} + {FILESTRING}+ { + String name = yytext().replaceAll("([\\\"]|[\\']|[\\{]|[\\}]|[\\[]|[\\]])+",""); + setError(location,"It is forbidden to use a file name such as " + name + " directly.", yyline+1); + escapeNext=false; + yybegin(YYINITIAL); + } + {COMMAND_END} {escapeNext=false; yybegin(YYINITIAL);} + {LEFT_FILE_REDIRECT}|{RIGHT_FILE_REDIRECT} + { + String name = yytext().replaceAll("([\\s]|[\\>]|[\\\"]|[\\']|[\\<]|[\\&]|[\\{]|[\\}])+",""); + setError(location,"It is forbidden to use a file name such as " + name + " directly.", yyline+1); + escapeNext=false; + yybegin(YYINITIAL); + } + . {} } +/************************/ +/* STRING STATE */ +/************************/ + + { + {ESCAPE} { + if(!escapeNext) + { + escapeNext=true; + } else + { + escapeNext=false; + } + } + {STRING} { + if(!escapeNext && yytext().equals(stringBeginner)) + { + yybegin(YYINITIAL); + } + escapeNext=false; + } + {COMMENT_WORD} {escapeNext=false;} + [^] {escapeNext=false;} + } + +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWRecursion.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWRecursion.lex index 8b95640b..844a088d 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWRecursion.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMFLOWRecursion.lex @@ -17,16 +17,20 @@ package fr.cnes.analysis.tools.shell.rules; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -41,28 +45,50 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, FUNCOMMENT, NAMING, FUNCTIONSTATE +%state COMMENT, NAMING, BEGINFUNC, STRING_DOUBLE, STRING_SIMPLE COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_\-]* +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] STRING = \'[^\']*\' | \"[^\"]*\" +IGNORE = "EOF" [^]* "EOF" + +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) + OPTCHAR = \# | \! | % | \* | @ | \^ | \' | , | \/ | : | = | \+ | \? EXTENDEDVAR = \$\{ {OPTCHAR}* {VAR} {OPTCHAR}* {VAR}? (\[)? {OPTCHAR}* (\])? \} -IGNORE = "EOF" [^]* "EOF" + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] %{ - String location = "MAIN PROGRAM"; - /** Map that contains all the functions with its calls **/ + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + int brackets = 0; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + + /** Map that contains all the functions with its calls **/ Map> functionCalls = new HashMap>(); /** Current list of calls **/ List calls = new ArrayList(); - /** Number of brackets **/ - int brackets = 0; + + private String parsedFileName; + private Stack functionStack = new Stack<>(); public COMFLOWRecursion() { } @@ -80,16 +106,51 @@ IGNORE = "EOF" [^]* "EOF" * @param * var: string called inside the current function */ - private void checkCircularCalling(String var) throws JFlexException { + private Boolean checkCircularCalling(String var) throws JFlexException { List callings = functionCalls.get(var); if (callings!=null) { - if (callings.contains(location)) setError(location,"The use of recursivity is not allowed.", yyline+1); + if (callings.contains(location)) { + setError(location,"The use of recursivity is not allowed.", yyline+1); + return true; + } else { - for (String element : callings) checkCircularCalling(element); + Boolean found = false; + for (String element : callings) { + found = checkCircularCalling(element); + if (found) return true; + } } } + return false; } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + List list = new ArrayList(calls); + functionCalls.put(location,list); + calls.clear(); + + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + List currentCalls = functionCalls.get(location); + if (currentCalls != null) + { + calls.addAll(currentCalls); + } + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + + %} %eofval{ @@ -114,21 +175,13 @@ IGNORE = "EOF" [^]* "EOF" . {} } -/************************/ -/* FUNCOMMENT STATE */ -/************************/ - - { - \n {yybegin(FUNCTIONSTATE);} - . {} - } - + /************************/ /* NAMING STATE */ /************************/ { - {VAR} {location = yytext(); brackets=0; yybegin(FUNCTIONSTATE);} + {FNAME} {location = yytext(); yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -139,38 +192,89 @@ IGNORE = "EOF" [^]* "EOF" { {COMMENT_WORD} {yybegin(COMMENT);} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); brackets=0; yybegin(FUNCTIONSTATE);} - {STRING} {} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); brackets=0; yybegin(BEGINFUNC);} + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {VAR} {/** call to the same function **/ + if(yytext().equals(location)) setError(location,"The use of recursivity is not allowed.", yyline+1); + /** save in list to verify circular calling **/ + else { + if (!functionStack.empty()){ + // we are in a function + checkCircularCalling(yytext()); + if (!calls.contains(yytext())) + calls.add(yytext()); + } + } + } . {} + } /************************/ -/* FUNCTIONSTATE STATE */ +/* BEGINFUNC STATE */ /************************/ - +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + { - {COMMENT_WORD} {yybegin(FUNCOMMENT);} - {STRING} {} - {EXTENDEDVAR} {} - {VAR} {/** call to the same function **/ - if(yytext().equals(location)) setError(location,"The use of recursivity is not allowed.", yyline+1); - /** save in list to verify circular calling **/ - else { - calls.add(yytext()); - checkCircularCalling(yytext()); - }} - \{(\#)? {brackets++;} - \} {brackets--; - if(brackets==0) { - List list = new ArrayList(calls); - functionCalls.put(location,list); - calls.clear(); - yybegin(YYINITIAL);}} - {IGNORE} {} - . {} + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBoolNegation.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBoolNegation.lex index e0097449..915b9e96 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBoolNegation.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBoolNegation.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,14 +42,24 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, LOGICAL +%state COMMENT, NAMING, LOGICAL, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" + +IGNORE = \$\{[^\}"\n"]*\} | \$\([^\)"\n"]*\) + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] NOT = \! OPER = \&\& | \|\| | \-"o" | \-"a" @@ -54,11 +67,19 @@ OPER = \&\& | \|\| | \-"o" | \-"a" %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; /** Bool to knkow if there are open brackets **/ int bracket = 0, brace = 0, parenth = 0; + private Stack functionStack = new Stack<>(); + public COMINSTBoolNegation() { } @@ -70,6 +91,22 @@ OPER = \&\& | \|\| | \-"o" | \-"a" this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} @@ -100,7 +137,7 @@ OPER = \&\& | \|\| | \-"o" | \-"a" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -111,10 +148,30 @@ OPER = \&\& | \|\| | \-"o" | \-"a" { {COMMENT_WORD} {yybegin(COMMENT);} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim();} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); yybegin(BEGINFUNC);} + {IGNORE} {} {NOT} {bracket=0; brace=0; parenth=0; yybegin(LOGICAL);} - {STRING} {} + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } [^] {} } @@ -135,6 +192,48 @@ OPER = \&\& | \|\| | \-"o" | \-"a" . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBrace.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBrace.lex index 960de83d..3b8e5611 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBrace.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTBrace.lex @@ -44,7 +44,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* @@ -159,7 +160,7 @@ BRACING = "expr" | "let" /************************/ { - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); yybegin(YYINITIAL);} + {FNAME} {location = yytext().substring(0,yytext().length()-2).trim(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTCodeComment.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTCodeComment.lex index 5a0b0a69..d5a76987 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTCodeComment.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTCodeComment.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -162,7 +163,7 @@ CLE = {RESERVED}| {POSIX} | {BUILTINS} /************************/ { - {VAR} {location = yytext(); loc.add(yytext()); yybegin(PREHEADER);} + {FNAME} {location = yytext(); loc.add(yytext()); yybegin(PREHEADER);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLine.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLine.lex index 27271234..98d32cf6 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLine.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLine.lex @@ -46,7 +46,8 @@ import java.util.logging.Logger; COMMENT_WORD = [\#] FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VALUE = [0-9][0-9]*([\.][0-9][0-9]*)? VAR = ([a-zA-Z][a-zA-Z0-9\_\-]*)|([$]([\-\@\?\#\!\_\*]|([a-zA-Z0-9]*)|[\{][a-zA-Z0-9]*[\}])) @@ -118,7 +119,7 @@ CONDITIONAL_STRUCT = [\[][\[]({VAR}|{SPACE}|{VALUE}|{OPERATOR}|{BRACKET})*[\]][ /************************/ { - {VAR} { + {FNAME} { location = yytext(); LOGGER.fine("["+this.parsedFileName+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : VAR \""+yytext()+"\" )"); yybegin(YYINITIAL);} diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLoopCondition.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLoopCondition.lex index 7580cb14..78da2a27 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLoopCondition.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMINSTLoopCondition.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -111,7 +112,7 @@ LOOP = {WHILE} | {UNTIL} /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMNAMEHomonymy.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMNAMEHomonymy.lex index 8534368a..a273eb16 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMNAMEHomonymy.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMNAMEHomonymy.lex @@ -44,7 +44,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z0-9\_\-]+ STRING = \'[^\']*\' | \"[^\"]*\" @@ -267,7 +268,7 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" /************************/ { - {VAR} {location = yytext(); functions.add(yytext()); yybegin(BEGINFUNC);} + {FNAME} {location = yytext(); functions.add(yytext()); yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMPRESHeader.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMPRESHeader.lex index 977e9f81..1d78b587 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMPRESHeader.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMPRESHeader.lex @@ -44,7 +44,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* | \$\# STRING = \'[^\']*\' | \"[^\"]*\" @@ -158,7 +159,7 @@ STRING = \'[^\']*\' | \"[^\"]*\" /************************/ { - {VAR} {if (first){ + {FNAME} {if (first){ errorLine = yyline + 1; location = yytext(); first=false; diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMPRESIndent.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMPRESIndent.lex index 1931ed3e..d1b9e581 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMPRESIndent.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMPRESIndent.lex @@ -19,12 +19,15 @@ import java.io.FileReader; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,29 +42,49 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, AVOID +%state COMMENT, NAMING, CONSUME_LINE, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACETAB}*[\(]{SPACETAB}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ + SPACE = [\ \r\f] TAB = [\t] SPACETAB = {SPACE}|{TAB} VAR = [a-zA-Z][a-zA-Z0-9\_]* CONTINUEDLINE = \\ {SPACETAB}* \n -BEGIN = "if" | "case" | "for" | "while" | - "until" +CASE_STMT = [^"\n""("" ""\r""\f""#"][^"\n""("]*\) + +CASE = "case" +ESAC = "esac" + +BEGIN = "if" | "case" | "for" | "while" | "until" CONT = "do" | "then" END = "done" | "fi" | "esac" ELSE = "else" | "elif" +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] + IGNORETEXT = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | ` [^`]* ` %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; int currentPos = 0, pos = 0; List desiredPos = new ArrayList(); @@ -69,10 +92,17 @@ IGNORETEXT = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | ` [^`]* ` Boolean inTabs = false; /* indentationRequired is true when the next line should be indented compared to the last */ Boolean indentationRequired = false; - /* avoid is true when the {} should not be taken into account */ - Boolean avoid = false; - /* checkEnd is true when in AVOID we are after a ";", requiring that ENDs should be taken into account */ + /* checkEnd is true when in CONSUME_LINE we are after a ";", requiring that ENDs should be taken into account */ Boolean checkEnd=false; + + /* firstInCase is true when the case statement is the first one of a case structure */ + Boolean firstInCase = false; + + /* decrementAtEnd is true when the body of the function is incremented, eg. when body is an if */ + /* with no { and is incremented compared to the function line */ + Boolean decrementAtEnd = false; + + private Stack functionStack = new Stack<>(); public COMPRESIndent() { desiredPos.add(0); @@ -105,7 +135,7 @@ IGNORETEXT = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | ` [^`]* ` indentationRequired = false; /* continue at same position */ } else { /* indentationRequired == false */ /* we are not at the beginning of a new indentation. The indentation should be the same as the last line */ - setError(location,"This line is not indented in comparison with the last one.", yyline+1); + setError(location,"This line should not be indented in comparison with the last one.", yyline+1); } } else { /* currentPos == value */ /* The indentation is what was expected */ @@ -142,10 +172,30 @@ IGNORETEXT = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | ` [^`]* ` if (index >= 0) { int value = desiredPos.get(index); if (currentPos != value) - setError(location,"This line is not indented in comparison with the last one.", yyline+1); + setError(location,"This line is not aligned with its corresponding structure.", yyline+1); } } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + if (decrementAtEnd) { + if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + decrementAtEnd = false; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} @@ -177,21 +227,60 @@ IGNORETEXT = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | ` [^`]* ` /************************/ { - {VAR} {location = yytext(); yybegin(AVOID);} + {FNAME} {location = yytext(); yybegin(BEGINFUNC);} \n {currentPos=0; yybegin(YYINITIAL);} . {} } /************************/ -/* AVOID STATE */ +/* CONSUME_LINE STATE */ /************************/ /* Consume characters till end of line */ - + { ; {checkEnd=true;} {COMMENT_WORD} {checkEnd=false; yybegin(COMMENT);} - {END} {if(checkEnd && desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);}} + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(STRING_DOUBLE);} + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(STRING_SIMPLE);} + {ESAC} { + if(checkEnd && desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + firstInCase = false; + } + {END} { + if(checkEnd && desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {FUNCEND} { /* for the remaining endings not in END */ + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } {IGNORETEXT} {} {CONTINUEDLINE} {} \n {checkEnd=false; currentPos=0; yybegin(YYINITIAL);} @@ -204,26 +293,225 @@ IGNORETEXT = "<<" {SPACE}* "EOF" [^"<<"]* "EOF" | ` [^`]* ` { {COMMENT_WORD} {inTabs=false; yybegin(COMMENT);} - {FUNCTION} {inTabs=false; checkIndentation(); indentationRequired=true; desiredPos.add(currentPos+1); yybegin(NAMING);} - {FUNCT} {inTabs=false; location = yytext().substring(0,yytext().length()-2).trim(); checkIndentation(); indentationRequired=true; desiredPos.add(currentPos+1); yybegin(AVOID);} - {BEGIN} {inTabs=false; checkIndentation(); indentationRequired=true; desiredPos.add(currentPos+1); yybegin(AVOID);} - {CONT} | {ELSE} {inTabs=false; checkIndentationElse(); indentationRequired=true; yybegin(AVOID);} - {END} {inTabs=false; if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} indentationRequired=false; checkIndentation(); yybegin(AVOID);} + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(STRING_DOUBLE);} + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(STRING_SIMPLE);} + {FUNCTION} { + inTabs=false; + checkIndentation(); + indentationRequired=true; + desiredPos.add(currentPos+1); + yybegin(NAMING); + } + {FUNCT} { + inTabs=false; + location = yytext().substring(0,yytext().length()-2).trim(); + checkIndentation(); + indentationRequired=true; + desiredPos.add(currentPos+1); + yybegin(BEGINFUNC); + } + {CASE} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + inTabs=false; + checkIndentation(); + indentationRequired=true; + desiredPos.add(currentPos+1); + /* Next case statement will be the first */ + firstInCase = true; + yybegin(CONSUME_LINE); + } + {BEGIN} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + inTabs=false; + checkIndentation(); + indentationRequired=true; + desiredPos.add(currentPos+1); + yybegin(CONSUME_LINE); + } + {CONT} | {ELSE} { + inTabs=false; + checkIndentationElse(); + indentationRequired=true; + yybegin(CONSUME_LINE); + } + {ESAC} { + inTabs=false; + if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + /* Another one to compensate for the added indentation of the previous case statement */ + if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + indentationRequired=false; + checkIndentation(); + firstInCase = false; + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + yybegin(CONSUME_LINE); + } + {END} { + inTabs=false; + if(desiredPos.size()>=1) { + desiredPos.remove(desiredPos.size()-1);} + indentationRequired=false; + checkIndentation(); + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + yybegin(CONSUME_LINE); + } {TAB} {pos=currentPos; currentPos+=yytext().length(); if(pos==0 | inTabs==true) { /* a tab was found at the beginning of a line */ inTabs=true; setError(location,"Tabulations are not allowed.", yyline+1); }} - {SPACE} {if(currentPos==0) {inTabs=true;}; currentPos+=yytext().length();} - {VAR} {inTabs=false; checkIndentation(); yybegin(AVOID);} + {SPACE}+ {if(currentPos==0) {inTabs=true;}; currentPos+=yytext().length();} + {VAR} {inTabs=false; checkIndentation(); yybegin(CONSUME_LINE);} {IGNORETEXT} {} - \{ {inTabs=false; yybegin(AVOID);} - \} {inTabs=false; if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} checkIndentationNoChange(); yybegin(AVOID);} + \{ { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + inTabs=false; + yybegin(CONSUME_LINE); + } + \} { + inTabs=false; + if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + checkIndentationNoChange(); + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + yybegin(CONSUME_LINE); + } + {FUNCSTART} { /* for the remaining beginnings not in BEGIN */ + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + yybegin(CONSUME_LINE); + } + {FUNCEND} { /* for the remaining endings not in END */ + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } \n {inTabs=false; currentPos=0;} - . {inTabs=false; checkIndentation(); yybegin(AVOID);} + {CASE_STMT} { + inTabs=false; + if (!firstInCase) { + if(desiredPos.size()>=1) {desiredPos.remove(desiredPos.size()-1);} + checkIndentationNoChange(); + } else { + firstInCase = false; + checkIndentation(); + } + indentationRequired=true; + desiredPos.add(currentPos+1); + yybegin(CONSUME_LINE); + } + . {inTabs=false; checkIndentation(); yybegin(CONSUME_LINE);} } - + +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + "\n"{SPACE}* { + currentPos = currentPos+yytext().length() -1; + decrementAtEnd = true; + } + {BEGIN} { + inTabs=false; + checkIndentation(); + indentationRequired=true; + desiredPos.add(currentPos+1); + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(CONSUME_LINE); + } + \{ { + inTabs=false; + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(CONSUME_LINE); + } + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(CONSUME_LINE); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(CONSUME_LINE);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(CONSUME_LINE);} + [^]|{SPACE} {} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMPRESLengthLine.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMPRESLengthLine.lex index 2e4e0565..8bea8a94 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMPRESLengthLine.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMPRESLengthLine.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,19 +42,38 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING +%state COMMENT, NAMING, BEGINFUNC, STRING_DOUBLE, STRING_SIMPLE -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* +COMMENT_WORD = \# +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; int length = 0; + private Stack functionStack = new Stack<>(); public COMPRESLengthLine() { @@ -70,7 +92,23 @@ VAR = [a-zA-Z][a-zA-Z0-9\_]* setError(location,"There are more than 100 characters in this line.", yyline+1); length = 0; } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} %eofval{ @@ -84,14 +122,25 @@ VAR = [a-zA-Z][a-zA-Z0-9\_]* /************************/ - +/************************/ +/* COMMENT STATE */ +/************************/ + + { + \n {checkLine(); yybegin(YYINITIAL);} + . {length+=yytext().length();} + } + /************************/ /* NAMING STATE */ /************************/ { - {VAR} {location = yytext(); length+=yytext().length(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); + length+=yytext().length(); + functionLine = yyline+1; + yybegin(BEGINFUNC);} \n {checkLine(); yybegin(YYINITIAL);} . {length+=yytext().length();} } @@ -101,12 +150,94 @@ VAR = [a-zA-Z][a-zA-Z0-9\_]* /************************/ { + {COMMENT_WORD} {length+=yytext().length();yybegin(COMMENT);} + {STRING_D} { + length+=yytext().length(); + yybegin(STRING_DOUBLE); + } + {STRING_S} { + length+=yytext().length(); + yybegin(STRING_SIMPLE); + } {FUNCTION} {length+=yytext().length(); yybegin(NAMING);} - {FUNCT} {length+=yytext().length(); location = yytext().substring(0,yytext().length()-2).trim(); } + {FUNCT} {length+=yytext().length(); + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + length+=yytext().length(); + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + length+=yytext().length(); + } \n {checkLine();} . {length+=yytext().length();} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {length+=yytext().length();} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + length+=yytext().length(); + yybegin(YYINITIAL); + } + [^]|{SPACE} {length+=yytext().length();} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {length+=yytext().length();} + {STRING_S} { + length+=yytext().length(); + yybegin(YYINITIAL); + } + [^]|{SPACE} {length+=yytext().length();} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {length+=yytext().length();} + {STRING_D} { + length+=yytext().length(); + yybegin(YYINITIAL); + } + [^]|{SPACE} {length+=yytext().length();} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/COMTYPEExpression.lex b/fr.cnes.analysis.tools.shell.rules/lex/COMTYPEExpression.lex index a1b3e8fb..d53471d8 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/COMTYPEExpression.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/COMTYPEExpression.lex @@ -44,7 +44,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -144,7 +145,7 @@ EXPR = {VARIABLE} {SPACE}+ {OPER} {SPACE}+ ({STRING}|{INT}|{VARIABLE}) /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHDATAIFS.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHDATAIFS.lex index 0ab46a01..8967df65 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHDATAIFS.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHDATAIFS.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -98,7 +99,7 @@ IFS = "IFS"\= /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHDATAInteger.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHDATAInteger.lex index 2e8313a6..0a2b0967 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHDATAInteger.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHDATAInteger.lex @@ -44,7 +44,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -104,7 +105,7 @@ TYPESET = "typeset"{SPACE}+\-"i" /************************/ { - {VAR} {location = yytext(); yybegin(LINE);} + {FNAME} {location = yytext(); yybegin(LINE);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHDESIGNOptions.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHDESIGNOptions.lex index 7ccfe7db..c5092fab 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHDESIGNOptions.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHDESIGNOptions.lex @@ -42,7 +42,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* @@ -121,7 +122,7 @@ ESAC = "esac" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHERRHelp.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHERRHelp.lex index e6e2c986..f02eb6ba 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHERRHelp.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHERRHelp.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -121,7 +122,7 @@ HELP = "help" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHERRNoPipe.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHERRNoPipe.lex index c2aa4d5c..480b83e0 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHERRNoPipe.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHERRNoPipe.lex @@ -46,7 +46,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -128,7 +129,7 @@ OR = \|\| /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {if(inCase){ yybegin(CASE); }else{ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHERRString.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHERRString.lex index fe24d30d..0d96f672 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHERRString.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHERRString.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -98,7 +99,7 @@ COMPARISON = ("if" | "while") {SPACE}* \[ {SPACE} /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckArguments.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckArguments.lex index 48a55e02..6035de27 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckArguments.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckArguments.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -51,7 +52,8 @@ STRING = \'[^\']*\' | \"[^\"]*\" COMP = "-eq" | "-ne" | "-gt" | "-ge" | "-lt" | "-le" | \< | \<\= | \> | \>\= -ARGS = "if"{SPACE}+\[{SPACE}+\$\#{SPACE}+{COMP} +ARGS = "if"{SPACE}+\[{SPACE}+{NUMBER_PARAMS}{SPACE}+{COMP} +NUMBER_PARAMS = \$\# | \$\{\#\} %{ String location = "MAIN PROGRAM"; @@ -106,7 +108,7 @@ ARGS = "if"{SPACE}+\[{SPACE}+\$\#{SPACE}+{COMP} /************************/ { - {VAR} {location = yytext(); yybegin(CHECKARGUMENTS);} + {FNAME} {location = yytext(); yybegin(CHECKARGUMENTS);} \n {yybegin(CHECKARGUMENTS);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckCodeReturn.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckCodeReturn.lex index 164099a0..c8c622e1 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckCodeReturn.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckCodeReturn.lex @@ -20,12 +20,15 @@ import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -40,19 +43,35 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, CHECKRET, FINLINE, COMMENTARGS, PIPELINE +%state COMMENT, NAMING, CHECKRET, FINLINE, COMMENTARGS, PIPELINE, CONSUMECOMMAND, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# SPACE = [\ \r\t\f] FUNCTION = "function" -FUNC = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" +PIPEIGNORE = "||" +PIPE = \| + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] %{ - private String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; /** Map with each function name and if contains a return or not **/ private Map functions = new HashMap(); @@ -65,6 +84,8 @@ STRING = \'[^\']*\' | \"[^\"]*\" /** Last function called **/ private String functionCall = ""; + private Stack functionStack = new Stack<>(); + public SHFLOWCheckCodeReturn() { /** The command 'cd' must be checked as the functions **/ functions.put("awk",true); @@ -117,14 +138,33 @@ STRING = \'[^\']*\' | \"[^\"]*\" this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} -%eofval{ - if(!verified && functionCalled) addViolation(); - return getCheckResults(); -%eofval} +/* ------------------------------------------------------------------------------------------------- */ +/* The eofval function has been removed to treat EOF differently when found in different states */ +/* This is due to the fact that the violation is raised when at least one of the following lines */ +/* has been parsed. According to what is parsed, the violation needs to be raised on a previous line */ +/* or not. */ +/* The eofval function MUST NOT be used in combination with EOF recognition in states (exclusive). */ +/* ------------------------------------------------------------------------------------------------- */ %% @@ -141,6 +181,7 @@ STRING = \'[^\']*\' | \"[^\"]*\" { \n {yybegin(YYINITIAL);} + <> {return getCheckResults();} . {} } @@ -149,8 +190,9 @@ STRING = \'[^\']*\' | \"[^\"]*\" /************************/ { - {VAR} {location = yytext(); functions.put(location, false); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functions.put(location, false); yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} + <> {return getCheckResults();} . {} } @@ -159,10 +201,13 @@ STRING = \'[^\']*\' | \"[^\"]*\" /************************/ { + {PIPEIGNORE} {pipeline = false;} {COMMENT_WORD} {yybegin(COMMENT);} - {FUNCTION} {location = yytext(); yybegin(NAMING);} - {FUNC} {location = yytext().substring(0,yytext().length()-2).trim(); functions.put(location, false);} - {STRING} {} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} + {PIPE} {pipeline = true;} + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); functions.put(location, false); yybegin(BEGINFUNC);} {VAR} {Boolean found = functions.get(yytext()); if(found!=null) { functionCalled=true; @@ -172,7 +217,27 @@ STRING = \'[^\']*\' | \"[^\"]*\" yybegin(FINLINE); } else { functionCalled=false; + yybegin(CONSUMECOMMAND); }} + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + <> {return getCheckResults();} [^] {} } @@ -181,8 +246,14 @@ STRING = \'[^\']*\' | \"[^\"]*\" /************************/ { - \| {pipeline = true; yybegin(PIPELINE);} + {PIPEIGNORE} {pipeline = false; yybegin(YYINITIAL);} + {PIPE} {pipeline = true; yybegin(PIPELINE);} \n {yybegin(CHECKRET);} + <> { + linesError=0; + if(!verified && functionCalled) addViolation(); + return getCheckResults(); + } . {} } @@ -196,11 +267,34 @@ STRING = \'[^\']*\' | \"[^\"]*\" functionCalled=true; verified=false; linesError=1; - functionCall+=", " + yytext(); + if (functionCall.length() != 0) functionCall+=", "; + functionCall+=yytext(); }} \n {yybegin(CHECKRET);} + <> { + linesError=0; + if(!verified && functionCalled) addViolation(); + return getCheckResults(); + } + . {} + } + +/************************/ +/* CONSUMECOMMAND STATE */ +/************************/ + + { + {PIPEIGNORE} {pipeline = false; yybegin(YYINITIAL);} + {PIPE} {pipeline = true; yybegin(PIPELINE);} + \n | ";" {yybegin(YYINITIAL);} + <> { + linesError=0; + if(!verified && functionCalled) addViolation(); + return getCheckResults(); + } . {} } + /************************/ @@ -208,7 +302,7 @@ STRING = \'[^\']*\' | \"[^\"]*\" /************************/ { - \# {yybegin(COMMENTARGS);} + {COMMENT_WORD} {yybegin(COMMENTARGS);} {VAR} {Boolean found = functions.get(yytext()); if(found!=null) { addViolation(); @@ -222,9 +316,15 @@ STRING = \'[^\']*\' | \"[^\"]*\" }} \$\? {verified=true;} {SPACE} {} - \n {if(!verified) addViolation(); + \n { + if(!verified) addViolation(); functionCalled = false; + functionCall=""; yybegin(YYINITIAL);} + <> { + if(!verified && functionCalled) addViolation(); + return getCheckResults(); + } . {} } @@ -234,9 +334,59 @@ STRING = \'[^\']*\' | \"[^\"]*\" { \n {linesError++; yybegin(CHECKRET);} + <> { + linesError=0; + if(!verified && functionCalled) addViolation(); + return getCheckResults(); + } . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + <> {return getCheckResults();} + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + <> {return getCheckResults();} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + <> {return getCheckResults();} + [^]|{SPACE} {} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckUser.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckUser.lex index 3b6b7861..9e50df1f 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckUser.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHFLOWCheckUser.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* @@ -128,7 +129,7 @@ DIRECT_CHECK = {DIRECT_USER} {SPACE}+ {OP} {SPACE}+ {ROOT_VALUE} /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTBasename.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTBasename.lex index 5f0a9976..b3b5539d 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTBasename.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTBasename.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* @@ -99,7 +100,7 @@ DIRNAME = "dirname"{SPACE}+\$"0" | "dirname"{SPACE}+\"\$"0"\" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTContinue.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTContinue.lex index 39b7ee02..afec7cff 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTContinue.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTContinue.lex @@ -42,7 +42,10 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %state COMMENT, NAMING, COMMENT_WORD = \# -FUNC = "function" +FUNCTION = "function" +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -92,7 +95,7 @@ CONTINUE = "continue" /************************/ { - {VAR} {location = location + yytext(); yybegin(YYINITIAL);} + {FNAME} {location = location + yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } @@ -104,7 +107,8 @@ CONTINUE = "continue" { {COMMENT_WORD} {yybegin(COMMENT);} {STRING} {} - {FUNC} {location = yytext(); yybegin(NAMING);} + {FUNCTION} {yybegin(NAMING);} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); } {CONTINUE} {setError(location,"The keyword CONTINUE is not allowed.", yyline+1); } {VAR} {} /* Clause to match with words that contains "continue" */ [^] {} diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTFind.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTFind.lex index 4afdb4b8..92366435 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTFind.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTFind.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_\/]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -98,7 +99,7 @@ LS = "ls" | "/bin/ls" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTGetOpts.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTGetOpts.lex index 2e362428..6b6597b8 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTGetOpts.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTGetOpts.lex @@ -44,7 +44,8 @@ import java.util.logging.Logger; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] PARAMETER = [\$](([1-9][0-9]*)|[\*]) VAR = ([a-zA-Z][a-zA-Z0-9\_\-]*)|([\$]([\-\@\?\#\!\_\0]|([a-zA-Z]*)|[\{][a-zA-Z]*[\}])) @@ -122,7 +123,7 @@ ESCAPE_STRING = [\\]([\']|[\"]) /************************/ { - {VAR} { + {FNAME} { LOGGER.fine("["+this.parsedFileName+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : VAR \""+yytext()+"\" )"); location = yytext(); functionContainGetOpt=false; @@ -197,7 +198,7 @@ ESCAPE_STRING = [\\]([\']|[\"]) LOGGER.fine("["+this.parsedFileName+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> YYINITIAL (Transition : VAR \""+yytext()+"\" )"); yybegin(STRING); } - {FUNCT} {} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim();} {GETOPT} { foundGetOpt=true; functionContainGetOpt=true; diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTLogical.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTLogical.lex index b51b77da..dec760db 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTLogical.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTLogical.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -101,7 +102,7 @@ ENDCOND = "do" | "then" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTPOSIX.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTPOSIX.lex index e7602fe8..59ac1c55 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTPOSIX.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTPOSIX.lex @@ -52,7 +52,8 @@ import java.util.regex.Matcher; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = ([a-zA-Z][a-zA-Z0-9\_\-]*)|([\$]([\-\@\?\#\!\_\*]|([a-zA-Z0-9]*)|[\{][a-zA-Z0-9]*[\}])) ECHO = "echo" @@ -168,7 +169,7 @@ VAR_ERROR = ([\$]{ERROR}) | ([\$][\{]{ERROR}[\}]) /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTSetShift.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTSetShift.lex index cfc8b5b8..689333c5 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHINSTSetShift.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHINSTSetShift.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -99,7 +100,7 @@ AVOID = "set"{SPACE}+\-"o"{SPACE}+"pipefail" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHIORedirect.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHIORedirect.lex index b01e7008..67fc8661 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHIORedirect.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHIORedirect.lex @@ -37,12 +37,15 @@ import java.io.FileReader; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -57,12 +60,13 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING +%state COMMENT, NAMING, BEGINFUNC COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* STRING = \'[^\']*\' | \"[^\"]*\" OPERATOR_RIGHT = [\>]|[\>][\&]|[\&][\>]|[\>][\>]|[\>][\>][\>] @@ -73,14 +77,24 @@ REDIRECT_LEFT = ([a-zA-Z3-9\_\?\-\/\\\}]|{STRING})+{SPACE}*({OPERATOR_LEFT}|{OPE REDIRECT_RL = ([a-zA-Z3-9\_\?\-\/\\\}]|{STRING})+{SPACE}*{OPERATOR_RL}{SPACE}*([a-zA-Z3-9\_\?\.\-\$\/\\]|{STRING})+ REDIRECT = {REDIRECT_RIGHT}|{REDIRECT_LEFT}|{REDIRECT_RL} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; List redirections = new ArrayList(); private boolean isLastLineCommented = false; private boolean errorReported=false; + private Stack functionStack = new Stack<>(); + public SHIORedirect() { } @@ -92,7 +106,24 @@ REDIRECT = {REDIRECT_RIGHT}|{REDIRECT_LEFT}|{REDIRECT_RL} this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + %} %eofval{ @@ -124,8 +155,8 @@ REDIRECT = {REDIRECT_RIGHT}|{REDIRECT_LEFT}|{REDIRECT_RL} /************************/ { - {VAR} { - location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} + \n { isLastLineCommented=false; yybegin(YYINITIAL);} @@ -147,13 +178,53 @@ REDIRECT = {REDIRECT_RIGHT}|{REDIRECT_LEFT}|{REDIRECT_RL} } } {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); } - {STRING} {} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {STRING} {} . {} \n {isLastLineCommented=false;errorReported=false;} } - +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + /************************/ /* ERROR STATE */ /************************/ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitAWK.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitAWK.lex index 0fdffcaa..d53446e1 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitAWK.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitAWK.lex @@ -43,7 +43,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_\/]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -97,7 +98,7 @@ STRING = \'[^\']*\' | \"[^\"]*\" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitSed.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitSed.lex index 623b5848..c0d93678 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitSed.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHMETLimitSed.lex @@ -42,7 +42,8 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_\/]* STRING = \'[^\']*\' | \"[^\"]*\" @@ -100,7 +101,7 @@ OPTION = "-e" | "--expression" | "-f" | "--file" | /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); yybegin(YYINITIAL);} \n {yybegin(YYINITIAL);} . {} } diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHMETPipeLine.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHMETPipeLine.lex index 0264c8bf..42cf46d3 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHMETPipeLine.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHMETPipeLine.lex @@ -19,12 +19,15 @@ import java.io.FileReader; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -40,18 +43,39 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, AVOID +%state COMMENT, NAMING, AVOID, CONSUME_LINE, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] + VAR = [a-zA-Z][a-zA-Z0-9\_]* PIPELINE = \|{SPACE} | \|\n | \|\& +CASE_STMT = [^"\n""("" ""\r""\f""#"][^"\n""("]*\) + +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] + %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + private Stack functionStack = new Stack<>(); + + /* location: the current function name, or main program, that is the initial value */ + private String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; int bracket = 0; String type = ""; @@ -69,22 +93,7 @@ PIPELINE = \|{SPACE} | \|\n | \|\& this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - - /** - * Check if the last not empty line is a comment or not - * @throws JFlexException - */ - private void checkPipelinesComments(int max) throws JFlexException { - int index = 1; - while(index <= max) { - String current = linesType.get(index); - if(current.equals("pipeline")){ - checkPrecedent(index, index+1); - } - index++; - } - } - + /** * Check the line before to the current line * @param index @@ -99,12 +108,26 @@ PIPELINE = \|{SPACE} | \|\n | \|\& } } + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } %} %eofval{ - int index = linesType.size()-1; - checkPipelinesComments(index); return getCheckResults(); %eofval} @@ -133,7 +156,7 @@ PIPELINE = \|{SPACE} | \|\n | \|\& /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {linesType.add("line"); type="empty"; yybegin(YYINITIAL);} . {} } @@ -144,17 +167,112 @@ PIPELINE = \|{SPACE} | \|\n | \|\& { {COMMENT_WORD} {yybegin(COMMENT);} + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); if(type.equals("empty")) type="line";} + {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); + if(type.equals("empty")) type="line"; + functionLine = yyline+1; + yybegin(BEGINFUNC); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } \|\| {} /** OR logique **/ + {CASE_STMT} {} /* a case statement can contain multiple choices with | -> ignore */ {PIPELINE} {type="pipeline"; - if(yytext().contains("\n")) {linesType.add(type); type="empty";} } + linesType.add(type); + type="empty"; + int index = linesType.size()-1; + checkPrecedent(index, yyline+1); + yybegin(CONSUME_LINE); + } {SPACE} {} \n {linesType.add(type); type="empty";} \\{SPACE}*\n {} . {if(type.equals("empty")) type="line";} } + +/************************/ +/* CONSUME_LINE STATE */ +/************************/ +/* Consume characters till end of line */ + + { + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + \n {yybegin(YYINITIAL);} + . {} + } + +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHREFExport.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHREFExport.lex index f519e0d8..034ac80f 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHREFExport.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHREFExport.lex @@ -18,12 +18,16 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; + import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,22 +43,39 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING +%state COMMENT, NAMING, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) -EXPORT = "export"{SPACE}+\-"f"{SPACE}+{VAR} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] +EXPORT = "export"{SPACE}+\-"f"{SPACE}+{FNAME} %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + private String parsedFileName; + int length = 0; + private Stack functionStack = new Stack<>(); public SHREFExport() { @@ -67,7 +88,24 @@ EXPORT = "export"{SPACE}+\-"f"{SPACE}+{VAR} this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + %} %eofval{ @@ -98,7 +136,9 @@ EXPORT = "export"{SPACE}+\-"f"{SPACE}+{VAR} /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); + functionLine = yyline+1; + yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -109,13 +149,88 @@ EXPORT = "export"{SPACE}+\-"f"{SPACE}+{VAR} { {COMMENT_WORD} {yybegin(COMMENT);} + {STRING_D} { + length+=yytext().length(); + yybegin(STRING_DOUBLE); + } + {STRING_S} { + length+=yytext().length(); + yybegin(STRING_SIMPLE); + } {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); } - {STRING} {} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC);} + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } {EXPORT} {setError(location,"It is forbidden to export functions.", yyline+1);} [^] {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {length+=yytext().length();} + {STRING_S} { + length+=yytext().length(); + yybegin(YYINITIAL); + } + [^]|{SPACE} {length+=yytext().length();} + } + +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {length+=yytext().length();} + {STRING_D} { + length+=yytext().length(); + yybegin(YYINITIAL); + } + [^]|{SPACE} {length+=yytext().length();} + } /************************/ /* ERROR STATE */ diff --git a/fr.cnes.analysis.tools.shell.rules/lex/SHSYNCSignals.lex b/fr.cnes.analysis.tools.shell.rules/lex/SHSYNCSignals.lex index 9b4d4ae2..5d44f8fa 100755 --- a/fr.cnes.analysis.tools.shell.rules/lex/SHSYNCSignals.lex +++ b/fr.cnes.analysis.tools.shell.rules/lex/SHSYNCSignals.lex @@ -18,12 +18,15 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.File; import java.util.List; +import java.util.EmptyStackException; +import java.util.Stack; import org.eclipse.core.runtime.Path; import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.Function; %% @@ -39,22 +42,38 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %type List -%state COMMENT, NAMING, TRAP +%state COMMENT, NAMING, TRAP, BEGINFUNC, STRING_SIMPLE, STRING_DOUBLE COMMENT_WORD = \# FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ SPACE = [\ \r\t\f] VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" + +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] TRAP = "trap" +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" %{ - String location = "MAIN PROGRAM"; + /* MAINPROGRAM: constant for main program localisation */ + private static final String MAINPROGRAM = "MAIN PROGRAM"; + + String location = MAINPROGRAM; + private String parsedFileName; + /* functionLine: the beginning line of the function */ + int functionLine = 0; + + private Stack functionStack = new Stack<>(); + public SHSYNCSignals() { } @@ -66,7 +85,25 @@ TRAP = "trap" this.parsedFileName = file.toString(); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - + + private void endLocation() throws JFlexException { + try{ + Function functionFinished = functionStack.pop(); + if (!functionStack.empty()) { + /* there is a current function: change location to this function */ + location = functionStack.peek().getName(); + } else { + /* we are in the main program: change location to main */ + location = MAINPROGRAM; + } + }catch(EmptyStackException e){ + final String errorMessage = e.getMessage(); + throw new JFlexException(this.getClass().getName(), parsedFileName, + errorMessage, yytext(), yyline, yycolumn); + } + } + + %} %eofval{ @@ -97,7 +134,7 @@ TRAP = "trap" /************************/ { - {VAR} {location = yytext(); yybegin(YYINITIAL);} + {FNAME} {location = yytext(); functionLine = yyline+1; yybegin(BEGINFUNC);} \n {yybegin(YYINITIAL);} . {} } @@ -109,8 +146,30 @@ TRAP = "trap" { {COMMENT_WORD} {yybegin(COMMENT);} {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location = yytext().substring(0,yytext().length()-2).trim(); } - {STRING} {} + {FUNCT} {functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + yybegin(BEGINFUNC); + } + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + functionStack.peek().addStarterRepetition(); + } + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + functionStack.peek().removeStarterRepetition(); + } else { + endLocation(); + } + } + } + } + {STRING_D} {yybegin(STRING_DOUBLE);} + {STRING_S} {yybegin(STRING_SIMPLE);} {TRAP} {yybegin(TRAP);} [^] {} } @@ -126,7 +185,50 @@ TRAP = "trap" . {} } +/************************/ +/* BEGINFUNC STATE */ +/************************/ +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + + { + \(\) {} + {FUNCSTART} { + Function function; + function = new Function(location, functionLine, yytext()); + functionStack.push(function); + yybegin(YYINITIAL); + } + [^]|{SPACE} {} + } + +/* + * The string states are designed to avoid problems due to patterns found in strings. + */ +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE_STRING_S} {} + {STRING_S} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE_STRING_D} {} + {STRING_D} {yybegin(YYINITIAL);} + [^]|{SPACE} {} + } + + /************************/ /* ERROR STATE */ /************************/ diff --git a/fr.cnes.analysis.tools.shell.rules/plugin.xml b/fr.cnes.analysis.tools.shell.rules/plugin.xml index 9a0e1018..9172ad3c 100755 --- a/fr.cnes.analysis.tools.shell.rules/plugin.xml +++ b/fr.cnes.analysis.tools.shell.rules/plugin.xml @@ -5,6 +5,16 @@ id="shell.rules" name="Shell Rules" point="fr.cnes.analysis.tools.analyzer.checks"> + + + + - - + + + + + + + + + + + + + + + + + + + + + diff --git a/fr.cnes.analysis.tools.shell.rules/pom.xml b/fr.cnes.analysis.tools.shell.rules/pom.xml index 40525123..435f866a 100644 --- a/fr.cnes.analysis.tools.shell.rules/pom.xml +++ b/fr.cnes.analysis.tools.shell.rules/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.shell.rules diff --git a/fr.cnes.analysis.tools.shell.rules/src/fr/cnes/analysis/tools/shell/rules/FunctionInvariant.java b/fr.cnes.analysis.tools.shell.rules/src/fr/cnes/analysis/tools/shell/rules/FunctionInvariant.java new file mode 100644 index 00000000..5a2977fa --- /dev/null +++ b/fr.cnes.analysis.tools.shell.rules/src/fr/cnes/analysis/tools/shell/rules/FunctionInvariant.java @@ -0,0 +1,58 @@ +package fr.cnes.analysis.tools.shell.rules; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class is added to handle functions and their local and global variables for the COMDATAInvariant rule. + * The COMDATAInvariant rule uses a hash table per function of variables that should be constants, and + * a list per function of variables that are either declared as constants or have been assigned more than once. + */ + +public class FunctionInvariant extends FunctionWithVariables { + + /* okVariables: contains all variables that have either been declared as consts or */ + /* should be variables. There should be no violation on them. */ + private ArrayList okVariables; + + /* okGlobalVariables: contains all global to the function variables that should be variables. + * There should be no violation on them. */ + private ArrayList okGlobalVariables; + + /* errVariables: contains all variables that for the moment should be consts */ + /* String: variable name, Integer: variable line in code */ + private HashMap errVariables; + + public FunctionInvariant(String pName, int pBeginLine, String pStarter) { + super(pName, pBeginLine, pStarter); + this.okVariables = new ArrayList(); + this.errVariables = new HashMap(); + this.okGlobalVariables = new ArrayList(); + } + + public HashMap getErrVariables() { + return this.errVariables; + } + + public ArrayList getOkVariables() { + return this.okVariables; + } + + public ArrayList getOkGlobalVariables() { + return this.okGlobalVariables; + } + + /* update ok and err variables with variable status from son function */ + public void addSonOkVariables(ArrayList sonOkVariables) { + for (String var : sonOkVariables) { + if (this.errVariables.containsKey(var)) { + this.errVariables.remove(var); + this.okVariables.add(var); + } + } + } + +} + diff --git a/fr.cnes.analysis.tools.shell.rules/src/fr/cnes/analysis/tools/shell/rules/FunctionWithVariables.java b/fr.cnes.analysis.tools.shell.rules/src/fr/cnes/analysis/tools/shell/rules/FunctionWithVariables.java new file mode 100644 index 00000000..9860b6d5 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.rules/src/fr/cnes/analysis/tools/shell/rules/FunctionWithVariables.java @@ -0,0 +1,45 @@ + +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ +package fr.cnes.analysis.tools.shell.rules; + +import java.util.ArrayList; + +import fr.cnes.analysis.tools.shell.metrics.Function; + +/** + * This class can be used to handle functions and their local and global variables. + */ +public class FunctionWithVariables extends Function { + + /* localVariables: the list of local variables in the function */ + private ArrayList localVariables = null; + /* globalVariables: the list of global variables in the function */ + private ArrayList globalVariables = null; + + /** + * @param pName + * Function's name + * @param pBeginLine + * Function's line + * @param pStarter + * Function's starter. + */ + public FunctionWithVariables(String pName, int pBeginLine, String pStarter) { + super(pName, pBeginLine, pStarter); + this.localVariables = new ArrayList(); + this.globalVariables = new ArrayList(); + } + + public ArrayList getLocalVariables() { + return this.localVariables; + } + + public ArrayList getGlobalVariables() { + return this.globalVariables; + } + +} diff --git a/fr.cnes.analysis.tools.ui/META-INF/MANIFEST.MF b/fr.cnes.analysis.tools.ui/META-INF/MANIFEST.MF index 81aa0b56..cbc3bd45 100755 --- a/fr.cnes.analysis.tools.ui/META-INF/MANIFEST.MF +++ b/fr.cnes.analysis.tools.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: i-Code CNES UI Bundle-SymbolicName: fr.cnes.analysis.tools.ui;singleton:=true -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: fr.cnes.analysis.tools.ui.Activator Require-Bundle: fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0", org.eclipse.core.runtime;bundle-version="3.11.0", diff --git a/fr.cnes.analysis.tools.ui/pom.xml b/fr.cnes.analysis.tools.ui/pom.xml index fec5c182..15f67dcc 100644 --- a/fr.cnes.analysis.tools.ui/pom.xml +++ b/fr.cnes.analysis.tools.ui/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.ui diff --git a/fr.cnes.icode.application/META-INF/MANIFEST.MF b/fr.cnes.icode.application/META-INF/MANIFEST.MF index 04aa0574..1fb974af 100644 --- a/fr.cnes.icode.application/META-INF/MANIFEST.MF +++ b/fr.cnes.icode.application/META-INF/MANIFEST.MF @@ -1,9 +1,9 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 -Bundle-Name: Shell command Application +Bundle-Name: i-Code CNES Command Line Application Bundle-SymbolicName: fr.cnes.icode.application;singleton:=true -Bundle-Version: 3.0.1.qualifier -Bundle-Vendor: Cnes +Bundle-Version: 3.1.0.qualifier +Bundle-Vendor: CNES Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.analyzer;bundle-version="2.0.0", @@ -16,5 +16,7 @@ Require-Bundle: org.eclipse.core.runtime, fr.cnes.analysis.tools.fortran90.metrics;bundle-version="2.0.0", fr.cnes.analysis.tools.fortran90.rules;bundle-version="2.0.0", fr.cnes.analysis.tools.shell.metrics;bundle-version="2.0.0", - fr.cnes.analysis.tools.shell.rules;bundle-version="2.0.0" + fr.cnes.analysis.tools.shell.rules;bundle-version="2.0.0", + org.apache.commons.cli;bundle-version="1.2.0", + org.apache.commons.io;bundle-version="2.2.0" Import-Package: org.apache.tools.ant diff --git a/fr.cnes.icode.application/build.properties b/fr.cnes.icode.application/build.properties index 0abc5835..1508451d 100644 --- a/fr.cnes.icode.application/build.properties +++ b/fr.cnes.icode.application/build.properties @@ -1,6 +1,6 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ + resources/logging.properties,\ .,\ - plugin.xml,\ - format2html.xslt + plugin.xml diff --git a/fr.cnes.icode.application/format2html.xslt b/fr.cnes.icode.application/format2html.xslt deleted file mode 100644 index e78dd14b..00000000 --- a/fr.cnes.icode.application/format2html.xslt +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - ICode <xsl:value-of select="@analysisProjectName" /> - - - -

ICode Analysis information

-
    -
  • - Project name : - -
  • -
  • - Version : - -
  • -
  • - Configuration ID : - -
  • -
  • - Date : - -
  • -
  • - Author : - -
  • - - - - - - -
- - - - -

- Analysis of - -

- - - - - - - - - - - - - -
Analysis Rule IDResult IDLineType PlaceName PlaceMessage
- - -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ No newline at end of file diff --git a/fr.cnes.icode.application/plugin.xml b/fr.cnes.icode.application/plugin.xml index 4adf1c50..bf1ff19a 100644 --- a/fr.cnes.icode.application/plugin.xml +++ b/fr.cnes.icode.application/plugin.xml @@ -15,12 +15,12 @@ + description="The product to run i-Code using a commande line " + name="i-Code CNES Command Line product"> diff --git a/fr.cnes.icode.application/pom.xml b/fr.cnes.icode.application/pom.xml index f161c8ab..2d05a197 100644 --- a/fr.cnes.icode.application/pom.xml +++ b/fr.cnes.icode.application/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.application diff --git a/fr.cnes.icode.application/resources/logging.properties b/fr.cnes.icode.application/resources/logging.properties new file mode 100644 index 00000000..1b67b9f9 --- /dev/null +++ b/fr.cnes.icode.application/resources/logging.properties @@ -0,0 +1,23 @@ +################################################################ +# logging.properties +# Contains configuration for i-Code configuration. +# +# Version: 1.0 +# Author: lequal +################################################################ + +# Use both file and console logging +handlers=java.util.logging.FileHandler + +# Based on INFO level to mute lower logs +.level=FINEST + +################################################################ +# CONFIG for all handlers +################################################################ + +# FileHandler configuration +java.util.logging.FileHandler.pattern=%h/.icode/log/icode-%g.log +java.util.logging.FileHandler.limit=100492 +java.util.logging.FileHandler.count=11 +java.util.logging.FileHandler.append = true \ No newline at end of file diff --git a/fr.cnes.icode.application/src/fr/cnes/icode/application/CommandLineManager.java b/fr.cnes.icode.application/src/fr/cnes/icode/application/CommandLineManager.java new file mode 100644 index 00000000..b57ab91e --- /dev/null +++ b/fr.cnes.icode.application/src/fr/cnes/icode/application/CommandLineManager.java @@ -0,0 +1,230 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ +package fr.cnes.icode.application; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.cli.BasicParser; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.UnrecognizedOptionException; + +/** + * Manage the command line by parsing it and providing preprocessed data. + * + * @author lequal + */ +public class CommandLineManager { + + /** + * Default logger. + */ + private final Logger LOGGER = Logger.getLogger(ICodeApplication.class.getName()); + + /** + * Possible options definition. + */ + private Options options; + /** + * Parser used by the manager. + */ + private CommandLineParser parser; + /** + * Formatter for automatic help. + */ + private HelpFormatter helpFormatter; + /** + * Contain the formatted cli. + */ + private CommandLine commandLine; + + /** + * Option short name for exporters. + */ + public static final String EXPORTERS = "e"; + /** + * Option short name for help. + */ + public static final String HELP = "h"; + /** + * Option short name for languages. + */ + public static final String LANGUAGES = "l"; + /** + * Option short name for rules. + */ + public static final String RULES = "r"; + /** + * Option short name for output filename. + */ + public static final String OUTPUT = "o"; + /** + * Option short name for excluded rules. + */ + public static final String EXCLUDED_RULES = "x"; + /** + * Option short name for checked languages. + */ + public static final String CHECKED_LANGUAGES = "c"; + /** + * Option short name for results format. + */ + public static final String EXPORT_FORMAT = "f"; + /** + * Option short name for export parameters. + */ + public static final String EXPORT_PARAMETERS = "p"; + /** + * Option short name for export parameters. + */ + public static final String LIST_EXPORT_PARAMETERS = "q"; + + /** + * Default construct which initialize and set options. + */ + public CommandLineManager() { + configure(); + } + + /** + * Set all members and prepare list of possible options + */ + private void configure() { + // Initialize values for members. + options = new Options(); + parser = new BasicParser(); + helpFormatter = new HelpFormatter(); + commandLine = null; + + // Add options + options.addOption(HELP, "help", false, + "Display this message."); + options.addOption(EXPORTERS, "exporters", false, + "Display all available exporters."); + options.addOption(LANGUAGES, "languages", false, + "Display all available languages."); + options.addOption(RULES, "rules", false, + "Display all available rules."); + options.addOption(LIST_EXPORT_PARAMETERS, "list-export-parameters", true, + "Display all available parameters for the given export."); + + options.addOption(OUTPUT, "output", true, + "Set the name for result file. Results are displayed in standard output by default."); + options.addOption(EXCLUDED_RULES, "excluded-rules", true, + "Comma separated list of rules id to exclude from analysis. None by default."); + options.addOption(CHECKED_LANGUAGES, "checked-languages", true, + "Comma separated list of languages checked during analysis. All by default."); + options.addOption(EXPORT_FORMAT, "export-format", true, + "Set the format for result file. Default format is XML."); + options.addOption(EXPORT_PARAMETERS, "export-parameters", true, + "Comma separated list of parameters for the export. Format is: key1=value1,key2=value2,key3=value3. Default values depend on the chosen export plugin."); + } + + /** + * Parse the provided command line. + * @param pArgs Arguments to parse. + */ + public void parse(final String[] pArgs) { + try { + boolean areOptionsCorrect = false; + try { + // Parse the command line. + commandLine = parser.parse(options, pArgs); + areOptionsCorrect = checkOptionsUse(commandLine); + } catch(UnrecognizedOptionException e) { + LOGGER.warning(e.getLocalizedMessage()); + areOptionsCorrect = false; + } + // If help option is present we print it. + if(!areOptionsCorrect || commandLine.hasOption(HELP)) { + helpFormatter.printHelp(128, "icode [ [...]]", + "Analyze Shell, F77 & F90 code to find defects & bugs.\n\n", options, + "\n\nPlease report issues at https://github.com/lequal/i-CodeCNES/issues", true); + System.exit(0); + } + } catch (ParseException e) { + LOGGER.log(Level.SEVERE, e.getMessage(), e); + } + } + + /** + * Check options compatibility: + * + Options EXPORTERS, HELP, LANGUAGES & RULES cannot be mixed with other options. + * + * @param commandLine Parsed command line. + * @return True if options respect requirements. + */ + private boolean checkOptionsUse(final CommandLine commandLine) { + // number of options which should be called alone + int standaloneOptions = 0; + // number of options without restriction + int analysisOptions = 0; + + for(final Option option : commandLine.getOptions()) { + if(option.getOpt().equals(HELP) + || option.getOpt().equals(EXPORTERS) + || option.getOpt().equals(LANGUAGES) + || option.getOpt().equals(RULES) + || option.getOpt().equals(LIST_EXPORT_PARAMETERS)) { + standaloneOptions++; + } else { + analysisOptions++; + } + } + + return (analysisOptions==0 || standaloneOptions==0) && standaloneOptions<2; + } + + /** + * Provides arguments as a list. + * + * @return A List with args. + */ + public List getArgs() { + List result; + + if(null!=commandLine) { + result = commandLine.getArgList(); + } else { + result = new ArrayList<>(); + } + + return result; + } + + /** + * Determine if an option is contained in the cli. + * + * @param pOption Name of the option to retrieve. + * @return True if the cli contains the option. + */ + public boolean hasOption(final String pOption) { + return commandLine!=null && commandLine.hasOption(pOption); + } + + /** + * Return the value of the corresponding option. + * + * @param pOption Name of the option. + * @return A string containing the value or an empty string. + */ + public String getOptionValue(final String pOption) { + String result = ""; + + if(null!=commandLine) { + result = commandLine.getOptionValue(pOption); + } + + return result; + } +} diff --git a/fr.cnes.icode.application/src/fr/cnes/icode/application/DisplayFormatter.java b/fr.cnes.icode.application/src/fr/cnes/icode/application/DisplayFormatter.java new file mode 100644 index 00000000..14733fa1 --- /dev/null +++ b/fr.cnes.icode.application/src/fr/cnes/icode/application/DisplayFormatter.java @@ -0,0 +1,46 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ +package fr.cnes.icode.application; + +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +/** + * Format log message to be displayed on the console. + * + * @author lequal + */ +public class DisplayFormatter extends Formatter { + + /** + * All printed message should comply to this format. + */ + private final String FORMAT_DEFAULT = "[%s] %s\n"; + + /** + * Following format is only for FINE level: we just print the message. + */ + private final String FORMAT_INFO = "%s\n"; + + /** + * Inherited method to format messages. + * @param pRecord Contain information provided to the logger. + * @return The formatted string as defined in FORMAT constant. + */ + @Override + public String format(LogRecord pRecord) { + // Default format applied at beginning + String message = String.format(FORMAT_DEFAULT, pRecord.getLevel().getLocalizedName(), pRecord.getMessage()); + + // If record level is INFO, we change the format. + if(pRecord.getLevel().equals(Level.INFO)) { + message = String.format(FORMAT_INFO, pRecord.getMessage()); + } + + return message; + } +} diff --git a/fr.cnes.icode.application/src/fr/cnes/icode/application/ICodeApplication.java b/fr.cnes.icode.application/src/fr/cnes/icode/application/ICodeApplication.java index 60ee88f9..fbf7bf98 100644 --- a/fr.cnes.icode.application/src/fr/cnes/icode/application/ICodeApplication.java +++ b/fr.cnes.icode.application/src/fr/cnes/icode/application/ICodeApplication.java @@ -1,584 +1,372 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ package fr.cnes.icode.application; +import java.io.BufferedReader; import java.io.File; +import java.io.FileReader; import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; +import java.util.Map; +import java.util.logging.ConsoleHandler; +import java.util.logging.LogManager; +import java.util.logging.Logger; +import org.apache.commons.io.FileUtils; import org.apache.tools.ant.DirectoryScanner; -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.ILog; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; -import org.osgi.framework.Bundle; -import org.osgi.framework.FrameworkUtil; import fr.cnes.analysis.tools.analyzer.Analyzer; import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.services.checkers.CheckerContainer; +import fr.cnes.analysis.tools.analyzer.services.checkers.CheckerService; +import fr.cnes.analysis.tools.analyzer.services.languages.LanguageContainer; import fr.cnes.analysis.tools.analyzer.services.languages.LanguageService; -import fr.cnes.analysis.tools.export.IExporter; -import fr.cnes.analysis.tools.export.csv.ExporterCsv; -import fr.cnes.analysis.tools.export.xml.ExporterXml; +import fr.cnes.analysis.tools.export.ExportService; +import fr.cnes.icode.application.exception.BadArgumentValueException; /** - * This is the application to launch icode with a line command. It can be launch - * with : - * - * icode myfile -> generate the result by default in XML format on sysout icode - * -f csv myfile -> generate the result by default in CSV format on sysout icode - * -output result.xml myfile -> generate the result.xml file for myfile icode - * -output result.csv myfile -> generate the result.csv file in CSV format - * - * The same can be done with as many files as necessary using pattenr : icode - * *.f + * This class provide a main command line application to + * use i-Code in a console without GUI. * - * @author olivier - * + * @author lequal */ public class ICodeApplication implements IApplication { - - private static final String FORMAT2HTML_XSLT = "format2html.xslt"; - - // ----------------------------------------------- - // Define the parameters for this application - // ----------------------------------------------- - /** help argument to display syntax */ - public static final String ARG_HELP = "-help"; //$NON-NLS-1$ - - /** Argument for verbose */ - public static final String ARG_VERBOSE = "-v"; //$NON-NLS-1$ - - /** - * The output format for the result: can be -f xml or -f csv.. default is - * XML - */ - public static final String ARG_OUTPUT_FORMAT = "-f"; //$NON-NLS-1$ - /** Expected value xml for output format */ - public static final String ARG_OUTPUT_FORMAT_XML = "xml"; //$NON-NLS-1$ - /** Expected value csv for output format */ - public static final String ARG_OUTPUT_FORMAT_CSV = "csv"; //$NON-NLS-1$ - - /** The optional output filename */ - public static final String ARG_OUTPUT_FILE = "-output"; //$NON-NLS-1$ - - /** The optional output HTML filename */ - public static final String ARG_HTML_OUTPUT_FILE = "-htmlOutput"; //$NON-NLS-1$ - - /** The optional html output format (only if xml is used) */ - public static final String ARG_HTML = "-html"; //$NON-NLS-1$ - - // -------------------------------------------------------------------------------------- - // Specific additional parameters only relevant for the XML output (no - // effect on - // CSV) - // -------------------------------------------------------------------------------------- - /** The optional author of analysis (for XML output) */ - public static final String ARG_AUTHOR = "-author"; //$NON-NLS-1$ - /** The optional project name (for XML output) */ - public static final String ARG_PROJECT = "-project"; //$NON-NLS-1$ - /** The optional project version (for XML output) */ - public static final String ARG_PROJECT_VERSION = "-projectVersion"; //$NON-NLS-1$ - /** The optional configuration ID (for XML output) */ - public static final String ARG_CONFIG_ID = "-configID"; //$NON-NLS-1$ - - private List availableArgs = Arrays.asList(new String[] { - ARG_HELP, ARG_VERBOSE, ARG_OUTPUT_FORMAT, ARG_OUTPUT_FILE, ARG_AUTHOR, ARG_PROJECT, - ARG_PROJECT_VERSION, ARG_CONFIG_ID, ARG_HTML_OUTPUT_FILE, ARG_HTML - }); - - // List args that are used alone (no parameters) - private List singleArgs = Arrays.asList(new String[] { - ARG_HELP, ARG_VERBOSE, ARG_HTML - }); - - /** output format to be used by default is XML */ - private String outputFormat = ARG_OUTPUT_FORMAT_XML; - - /** output filename to be used, by default sysout */ - private String outputFilename = null; - - /** Output file depending on -output or temporary file */ - private File outputFile = null; - - /** HTML output filename to be used, by default sysout */ - private String htmlOutputFilename = null; - - /** Real HTML file created (with parameter or temporary) */ - private File htmlOutputFile = null; - - /** verbose mode (default is false) */ - private boolean verbose = false; - - /** HTML output (default is false) */ - private boolean htmlOutput = false; - - public boolean isHtmlOutput() { - return htmlOutput; - } - - public void setHtmlOutput(boolean htmlOutput) { - this.htmlOutput = htmlOutput; - } - - /** config ID */ - private String configID = null; - - private String projectName, projectVersion, author; - - private String[] args; - - private List filenames = new ArrayList(); - - // Logger information - private ILog log; - private String pluginId = FrameworkUtil.getBundle(getClass()).getSymbolicName(); - - // The current exporter to use. - private IExporter exporter; - - @Override - public Object start(IApplicationContext context) throws Exception { - - args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS); - log = Platform.getLog(FrameworkUtil.getBundle(getClass())); - - getBooleanArg(ARG_VERBOSE, v -> setVerbose(v)); - getBooleanArg(ARG_HTML, v -> setHtmlOutput(v)); - - if (verbose) - info("Running ICode Analyzer "); - - // ------------------------------------- - // 1. Check for help (will exit if found) - // ------------------------------------- - if (args.length == 0) - setHelp(true); - getBooleanArg(ARG_HELP, v -> setHelp(v)); - - // ----------------------------------------------------- - // 2. Extract filenames from command line and check args - // ----------------------------------------------------- - int indexFiles = 0; - for (String s : args) { - // Consider to have the list of files at the end of the command line - // after the - // last argument - // Consider also to have only arguments with values : -f xml -output - // filename - // .... - // No single argument without values - // Skip all arguments to get filename index - if (s.startsWith("-")) { - indexFiles += ((singleArgs.contains(s) ? 1 : 2)); // Add 1 for - // single - // arguments, - // else add 2 - // Check if argument exists - if (!availableArgs.contains(s)) { - warning("The argument name '" + s - + "' is not expected for this command. Check help : "); - setHelp(true); - } - } - } - - for (int a = indexFiles; a < args.length; a++) - filenames.add(args[a]); - - // Resolve the file names - List files = resolveFileNames(); - - // Call help if no file names - if (files.size() == 0) { - warning("No input files (or non existing file(s)) in your command arguments."); - setHelp(true); - } - - if (verbose) { - info(" -> Filenames :" + filenames); - for (File f : files) - System.out.println("\t\t\tReal file : " + f.getAbsolutePath() - + (f.exists() ? "" : " -> Warning : does not exists")); - } - - // ------------------------------------- - // 3. Get other arguments - // ------------------------------------- - getArgValue(ARG_OUTPUT_FORMAT, v -> setOutputFormat(v)); - getArgValue(ARG_OUTPUT_FILE, v -> setOutputFilename(v)); - getArgValue(ARG_HTML_OUTPUT_FILE, v -> setHtmlOutputFilename(v)); - getArgValue(ARG_AUTHOR, v -> setAuthor(v)); - getArgValue(ARG_PROJECT, v -> setProjectName(v)); - getArgValue(ARG_PROJECT_VERSION, v -> setProjectVersion(v)); - getArgValue(ARG_CONFIG_ID, v -> setConfigID(v)); - - // Display additional verbose information if optional parameters were - // missing - if (verbose) { - if (outputFilename == null) - info(" -> Output filename : " + getOutputFile().getAbsolutePath()); - if (outputFormat == ARG_OUTPUT_FORMAT_XML && htmlOutputFilename == null) - info(" -> HTML Output filename (tmp) : " + getHtmlOutputFile().getAbsolutePath()); - - } - - // ------------------------------------------------------------------- - // 4. Can now launch the job using the Analyzer and export the results - // ------------------------------------------------------------------- - Analyzer analyzer = new Analyzer(); - - List checks = analyzer.check(files, LanguageService.getLanguagesIds(), null); - exporter = getExporter(); - - File outputFile = getOutputFile(); - if (outputFile == null) { - warning("Unable to create temporary file, use -output option"); - setHelp(true); - } - - exporter.export(checks, outputFile, exporter.getParameters()); - - // print the file content if no outputfilename (-> temporary file) - if (outputFilename == null) { - displayFile(outputFile); - } - - // Try to launch HTML processing - if (isHtmlOutput()) { - generateHtml(outputFile); - // Print the HTML result if any and if no XML already displayed and - // no HTML - // output provided - if (outputFilename != null && htmlOutputFilename == null) - displayFile(getHtmlOutputFile()); - } - - return EXIT_OK; - } - - private void generateHtml(File xmlInputFile) throws TransformerFactoryConfigurationError, - URISyntaxException, TransformerConfigurationException, TransformerException { - TransformerFactory factory = TransformerFactory.newInstance(); - Bundle b = FrameworkUtil.getBundle(getClass()); - URL xslUrl = b.getEntry(FORMAT2HTML_XSLT); - - File dataFile = null; - try { - dataFile = new File(FileLocator.resolve(xslUrl).toURI()); - } catch (URISyntaxException e1) { - e1.printStackTrace(); - } catch (IOException e1) { - e1.printStackTrace(); - } - - Source xslt = new StreamSource(dataFile); - Transformer transformer = factory.newTransformer(xslt); - - Source text = new StreamSource(xmlInputFile); - File result = getHtmlOutputFile(); - transformer.transform(text, new StreamResult(result)); - } - - private void displayFile(File outputFile) { - try { - System.out.print(new String(Files.readAllBytes(outputFile.toPath()))); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - private void setHelp(Boolean help) { - System.out.println("Minimal Usage : \n\n\ticode files...\n"); - System.out.println( - "This will print the result in console using the default output in XML format.\n"); - System.out.println( - "Files can be either absolute paths or patterns like : \t icode *.f90 ~/tmp/**/*.f77 /tmp/myfile.f77\n"); - System.out.println("Examples : "); - System.out.println("*.f90 : all the f90 files in current directory "); - System.out.println( - "~/tmp/**/*.f77 : all files with f77 extension in $HOME/tmp and any of its sub directoryies"); - System.out.println("/tmp/myfile.f77 : the specific file /tmp/myfile.f77"); - System.out.println("\nAvailable options : "); - System.out.println( - "\t-v : verbose, will display some traces, namely the files found in pattern"); - System.out.println("\t-f [xml | csv] : output format. Can be xml or csv."); - System.out.println( - "\t-output filename : optional, filename to store the xml or csv result. If none will be displayed in shell "); - System.out.println("\t-html : display html output (only for xml output with -output) "); - System.out.println( - "\t-htmlOutput filename : optional, filename to store the html transformation"); - System.out.println( - "\nFor XML output format these optional parameters can be used in any order : \n"); - System.out.println( - "\t\t-project yourProject -projectVersion yourVersion -author yourName -configID yourID \n"); - System.out.println( - "\nFor HTML output format it is possible to specify the html output file. \nIf none and no xml output file provided, html result will be displayed in shell \n"); - System.out.println("The XML and HTML parameters are not used by CSV format\n"); - System.out.println("Examples:"); - System.out.println("\ticode -f xml -output result.xml *.f "); - System.out.println("\ticode -f xml -author Me -output result.xml *.f "); - System.out.println("\ticode -f xml -author Me -project MyProject -output result.xml *.f "); - System.out.println( - "\ticode -f xml -author Me -project MyProject -projectVersion 1.2.0 -output result.xml *.f "); - - System.out.println("\ticode -html *.f "); - System.out.println("\ticode -f xml -output result.xml -html *.f "); - System.out.println("\ticode -f xml -output result.xml -html -htmlOutput result.html *.f "); - - System.exit(0); - } - - /** Resolve the files if there are wildcards inside */ - private List resolveFileNames() { - List result = new ArrayList<>(); - - // Convert parameters into array of Strings for scanner - String[] names = new String[filenames.size()]; - int i = 0; - for (String n : filenames) { - names[i++] = n; - } - - DirectoryScanner scanner = new DirectoryScanner(); - scanner.setIncludes(names); - // Scan with absolute path in scan - scanner.setCaseSensitive(false); - scanner.scan(); - scanFiles(scanner, result); - // Scan again with basedir for relative path in scan + + /** + * Logger for the current class @see /logging.properties for more information. + */ + private final static Logger LOGGER = Logger.getLogger(ICodeApplication.class.getName()); + + // Static initialization to set logging configuration. + static { + // Configure logging system + try (InputStream fis = ICodeApplication.class.getResourceAsStream("/resources/logging.properties")) { + LogManager manager = LogManager.getLogManager(); + manager.readConfiguration(fis); + ConsoleHandler handler = new ConsoleHandler(); + handler.setFormatter(new DisplayFormatter()); + LOGGER.addHandler(handler); + } catch (IOException e) { + throw new ExceptionInInitializerError(e); + } + // Configure temp files: creation of folder ~/.icode/log to contain log files + (new File(FileUtils.getUserDirectory().getPath().concat("/.icode/log"))).mkdirs(); + } + + /** + * Contains language's name as key and language's id as key. + */ + private Map languages; + + /** + * Manage the parsing and formatting of data provided by cli. + */ + private CommandLineManager cli; + + /** + * Needed services for running i-Code. + */ + private ExportService exportService; + + /** + * Set an analyzer. + */ + private Analyzer analyzer; + + /** + * List of language id (not name). + */ + private List checkedLanguages; + + /** + * List of rule id. + */ + private List excludedRules; + + /** + * Format of the export (xml by default). + */ + private String exportFormat; + + /** + * File where write results (a temp file is created by default). + */ + private File outputFile; + + /** + * Boolean true if output is the console. + */ + private boolean outputToStdOut; + + /** + * Default constructor to set available languages data. + */ + public ICodeApplication() { + super(); + + // Initialize services. + cli = new CommandLineManager(); + exportService = new ExportService(); + analyzer = new Analyzer(); + + // Analysis parameters with default values + languages = new HashMap<>(); + checkedLanguages = LanguageService.getLanguagesIds(); + excludedRules = new ArrayList<>(); + // default export format is set to XML + exportFormat = "xml"; + // init a temp file to retrieve results for displaying on screen + try { + outputFile = File.createTempFile("icode", ".res"); + outputFile.deleteOnExit(); + } catch (IOException e) { + LOGGER.warning(e.getLocalizedMessage()); + } + // by default results are printed to screen + outputToStdOut = true; + + // build map for translating languages' name to id + for(final LanguageContainer container : LanguageService.getLanguages()) { + languages.put(container.getName(), container.getId()); + } + } + + /** + * Main program's entry. + * + * @param pContext Arguments passed in command line. + * @throws Exception Able to throw all exceptions. + */ + @Override + public Object start(IApplicationContext pContext) throws Exception { + + try { + // Retrieve arguments from eclipse context. + final String [] args = (String[]) pContext.getArguments().get(IApplicationContext.APPLICATION_ARGS); + // Parse the command line arguments. + cli.parse(args); + + // Get list of filenames. + final List arguments = cli.getArgs(); + final String[] filenames = arguments.toArray(new String[arguments.size()]); + + // Get list of files to analyze. + final List sources = getFiles(filenames); + + // Export parameters. + Map exporterParameters; + + // Handle options. + if(cli.hasOption(CommandLineManager.EXPORTERS)) { + // display all available exporters + displayList(new ArrayList<>(exportService.getAvailableFormats().values()), + "List of available exporters for analysis:"); + } else if(cli.hasOption(CommandLineManager.LANGUAGES)) { + // display all available languages + displayList(languages.keySet(), + "List of available languages for analysis:"); + } else if(cli.hasOption(CommandLineManager.RULES)) { + // display all available checks by language + for(final LanguageContainer language : LanguageService.getLanguages()) { + displayList(CheckerService.getCheckersIds(language.getId()), + String.format("List of available rules for %s [%s]:", language.getName(), language.getId())); + } + } else if(cli.hasOption(CommandLineManager.LIST_EXPORT_PARAMETERS)) { + // Get format as value of the option. + exportFormat = cli.getOptionValue(CommandLineManager.LIST_EXPORT_PARAMETERS); + + if(exportService.getAvailableFormats().containsValue(exportFormat)) { + // Get default parameters for the chosen export. + exporterParameters = exportService.getParameters(exportFormat); + + // Security in the case of a null return. + if(exporterParameters==null) { + exporterParameters = new HashMap<>(); + } + + // display all available languages + displayList(exporterParameters.keySet(), + String.format("List of available parameters for %s export:", exportFormat)); + } else { + String message = String.format("Exporting in format '%s' is not available in i-Code.", exportFormat); + throw new BadArgumentValueException(message); + } + } else { + // Get list of languages id to check. + if(cli.hasOption(CommandLineManager.CHECKED_LANGUAGES)) { + checkedLanguages = Arrays.asList(cli.getOptionValue(CommandLineManager.CHECKED_LANGUAGES).split(",")); + for(final String id : checkedLanguages) { + if(!languages.containsKey(id)) { + String message = String.format("Language '%s' is not available in i-Code.", id); + throw new BadArgumentValueException(message); + } + } + // Translate Name to Id + for(int i = 0 ; i < checkedLanguages.size() ; i++) { + checkedLanguages.set(i, languages.get(checkedLanguages.get(i))); + } + } + // Get list of excluded rules. + if(cli.hasOption(CommandLineManager.EXCLUDED_RULES)) { + List checkers = CheckerService.getCheckers(); + Iterator iterator; + for(final String rule : cli.getOptionValue(CommandLineManager.EXCLUDED_RULES).split(",")) { + iterator = checkers.iterator(); + boolean found = false; + while(iterator.hasNext() && !found) { + CheckerContainer checker = iterator.next(); + found = checker.getId().equals(rule); + } + + // if the rule does not exist, just warn the user + if(!found) { + String message = String.format("Rule '%s' is not available in i-Code.", rule); + LOGGER.warning(message); + } else { // otherwise we add it to skipped checks + excludedRules.add(rule); + } + } + } + // Get export format from command line. + if(cli.hasOption(CommandLineManager.EXPORT_FORMAT)) { + exportFormat = cli.getOptionValue(CommandLineManager.EXPORT_FORMAT); + if(!exportService.getAvailableFormats().containsValue(exportFormat)) { + String message = String.format("Exporting in format '%s' is not available in i-Code.", exportFormat); + throw new BadArgumentValueException(message); + } + } + // Get the filename for result file and prevent i-Code to write in stdout. + if(cli.hasOption(CommandLineManager.OUTPUT)) { + outputFile = new File(cli.getOptionValue(CommandLineManager.OUTPUT)); + outputToStdOut = false; + } + + // Run the analysis. + final List checkResults = analyzer.check(sources, checkedLanguages, excludedRules); + // Get default parameters for the chosen export. + exporterParameters = exportService.getParameters(exportFormat); + + // Add user parameters if there are some. + if(cli.hasOption(CommandLineManager.EXPORT_PARAMETERS)) { + // Split all pairs of key=value. + final String[] params = cli.getOptionValue(CommandLineManager.EXPORT_PARAMETERS).split(","); + + // For each key=value. + for(final String param : params) { + // Split key from the value. + final String[] values = param.split("="); + // There should be 2 parts (key and value). + if(values.length==2) { + // If the key exist in map of default parameters we add the parameter to it. + if(exporterParameters.containsKey(values[0])) { + exporterParameters.put(values[0], values[1]); + } else { + String message = String.format("Export parameter '%s' is not a valid parameter for %s export.", + values[0], exportFormat); + throw new BadArgumentValueException(message); + } + } else { + String message = String.format("Export parameter '%s' is malformed.", param); + throw new BadArgumentValueException(message); + } + } + } + + // Export results to a file. + exportService.export(checkResults, outputFile, exporterParameters, exportFormat); + + // Display data to standard output if no file is asked by the user. + if(outputToStdOut) { + try (BufferedReader br = new BufferedReader(new FileReader(outputFile))) { + String line = null; + while ((line = br.readLine()) != null) { + LOGGER.info(line); + } + } + } + } + } catch(BadArgumentValueException e) { + LOGGER.severe(e.getMessage()); + } + + return EXIT_OK; + } + + /** + * Print a formatted list to the log output with an optional header. + * + * @param list List containing data to print. + * @param header String which can be printed before the list. + */ + private void displayList(final Collection list, final String header) { + // if header exists, we print it + if(header!=null && !header.isEmpty()) { + LOGGER.info(header); + } + + // print each line of a list + if(list!=null) { + for(final String item : list) { + LOGGER.info(String.format("+ %s", item)); + } + } + } + + /** + * Retrieve files to analyze from list of path with wildcards. + * + * @param pFilenames Array containing path of researched files. + * @return List of found files. + */ + private List getFiles(String[] pFilenames) { + // List of files found (to be returned) + final List result = new ArrayList<>(); + // Object used to browse directories and find files with shell regex + final DirectoryScanner scanner = new DirectoryScanner(); + // Temp object for file opening + File file = null; + + // Add user inputs as scope for research + scanner.setIncludes(pFilenames); + // Research must be case sensitive + scanner.setCaseSensitive(true); + // Set base directory as the current directory scanner.setBasedir(new File(".")); - if (verbose) - info("Base dir for scan is : " + scanner.getBasedir().getAbsolutePath()); - scanner.scan(); - scanFiles(scanner, result); - - return result; - } + // Scan for files + scanner.scan(); - private void scanFiles(DirectoryScanner scanner, List result) { + // Open found files for (String name : scanner.getIncludedFiles()) { - File f = new File(name); - if (!f.exists()) - warning("\t\tthe file '" + name + "' does not exist"); - else - result.add(f); - } - } - - private void setOutputFilename(String v) { - if ((v != null) && v.length() > 0) - outputFilename = v; - else - outputFilename = null; - - if (verbose) - info(" -> Output filename : " + outputFilename); - - } - - public String getHtmlOutputFilename() { - return htmlOutputFilename; - } - - public void setHtmlOutputFilename(String v) { - if ((v != null) && v.length() > 0) - htmlOutputFilename = v; - else - htmlOutputFilename = null; - - if (verbose) - info(" -> HTML Output filename : " + htmlOutputFilename); - } - - private File getOutputFile() { - if (outputFile == null) { - if (outputFilename != null) - outputFile = new File(outputFilename); - else { - try { - outputFile = File.createTempFile("icodeResult", outputFormat); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return outputFile; - } - - private File getHtmlOutputFile() { - if (htmlOutputFile == null) { - if (htmlOutputFilename != null) - htmlOutputFile = new File(htmlOutputFilename); - else { - try { - htmlOutputFile = File.createTempFile("icodeResult", ".html"); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return htmlOutputFile; - } - - /** Set the config file if any */ - private void setConfigID(String v) { - configID = v; - } - - private String getConfigID() { - return configID; - } - - private void setProjectName(String projectName) { - this.projectName = projectName; - } - - private void setProjectVersion(String projectVersion) { - this.projectVersion = projectVersion; - } - - private void setAuthor(String author) { - this.author = author; - } - - private String getProjectName() { - return projectName; - } - - private String getAuthor() { - return author; - } - - public String getProjectVersion() { - return projectVersion; - } - - public boolean isVerbose() { - return verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - private void setOutputFormat(String value) { - if (ARG_OUTPUT_FORMAT_CSV.equals(value)) { - outputFormat = ARG_OUTPUT_FORMAT_CSV; - // No html output for csv - if (verbose && htmlOutput) - info(" -> The -html argument is useless. Can be applied only if output is XML"); - htmlOutput = false; - } else if (ARG_OUTPUT_FORMAT_XML.equals(value)) { - outputFormat = ARG_OUTPUT_FORMAT_XML; - } else - warning("Parameter for outputFileFormat (-f) must be 'csv' or 'xml', default is 'xml'"); - - if (verbose) - info(" -> Output format : " + outputFormat); - - } - - private IExporter getExporter() { - IExporter result = null; - if (outputFormat == ARG_OUTPUT_FORMAT_XML) { - result = new ExporterXml(); - configureXMLExporter(result, ExporterXml.PARAM_AUTHOR, () -> getAuthor()); - configureXMLExporter(result, ExporterXml.PARAM_PROJECT_NAME, () -> getProjectName()); - configureXMLExporter(result, ExporterXml.PARAM_PROJECT_VERSION, - () -> getProjectVersion()); - configureXMLExporter(result, ExporterXml.PARAM_CONFIGURATION_ID, () -> getConfigID()); - } else { - result = new ExporterCsv(); + file = new File(name); + if (!file.exists()) { + LOGGER.warning(String.format("File not found: %s", name)); + } else { + result.add(file); + } } return result; - } - - private void configureXMLExporter(IExporter exporter, String propertyName, - Supplier supplier) { - String value = supplier.get(); - if (value != null) - exporter.getParameters().put(propertyName, value); } - /* - * (non-Javadoc) - * - * @see org.eclipse.equinox.app.IApplication#stop() - */ - @Override - public void stop() { - // TODO Auto-generated method stub - - } - - private void warning(String message) { - log.log(new Status(Status.WARNING, pluginId, message)); - System.out.println("\n Warning : " + message + "\n"); - } - - private void info(String message) { - System.out.println(message); - } - - /** - * This method extract an argument value and set it on the appropriate - * method - * - * @param argName - * argument name followed by a value - * @param consumer - * the method to call to initialize the value - */ - private void getArgValue(String argName, Consumer consumer) { - - for (int i = 0; i < args.length; i++) { - if (argName.equals(args[i]) && i + 1 < args.length) { - consumer.accept(args[i + 1]); - break; - } - } - - } - - /** - * This method extract a boolean argument and set it on the appropriate - * method - * - * @param argName - * argument name followed by a value - * @param consumer - * the method to call to initialize the value - */ - private void getBooleanArg(String argName, Consumer consumer) { - - for (int i = 0; i < args.length; i++) { - if (argName.equals(args[i])) { - consumer.accept(Boolean.TRUE); - break; - } - } - - } + /** + * Method executed after the end of the main program. + */ + @Override + public void stop() { + // Nothing to do at stop. + } } diff --git a/fr.cnes.icode.application/src/fr/cnes/icode/application/exception/BadArgumentValueException.java b/fr.cnes.icode.application/src/fr/cnes/icode/application/exception/BadArgumentValueException.java new file mode 100644 index 00000000..5c29fa45 --- /dev/null +++ b/fr.cnes.icode.application/src/fr/cnes/icode/application/exception/BadArgumentValueException.java @@ -0,0 +1,35 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ +package fr.cnes.icode.application.exception; + +/** + * This exception should be thrown when no contributor could be reached while + * requesting a contributor on an element inside. + */ +public class BadArgumentValueException extends Exception { + + /** + * Serial version UID. + */ + private static final long serialVersionUID = -6209005999854926693L; + + /** + * Default constructor. + */ + public BadArgumentValueException() { + super(); + } + + /** + * Constructor with a message as parameter. + * + * @param message + * The exception message. + */ + public BadArgumentValueException(final String message) { + super(message); + } +} diff --git a/fr.cnes.icode.feature.core/feature.xml b/fr.cnes.icode.feature.core/feature.xml index 12def9a0..7382e855 100755 --- a/fr.cnes.icode.feature.core/feature.xml +++ b/fr.cnes.icode.feature.core/feature.xml @@ -2,7 +2,7 @@ diff --git a/fr.cnes.icode.feature.core/pom.xml b/fr.cnes.icode.feature.core/pom.xml index aa377168..edda864e 100644 --- a/fr.cnes.icode.feature.core/pom.xml +++ b/fr.cnes.icode.feature.core/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.feature.core diff --git a/fr.cnes.icode.feature.fortran77/feature.xml b/fr.cnes.icode.feature.fortran77/feature.xml index 54b059aa..ae598792 100755 --- a/fr.cnes.icode.feature.fortran77/feature.xml +++ b/fr.cnes.icode.feature.fortran77/feature.xml @@ -2,7 +2,7 @@ @@ -210,8 +210,8 @@ litigation. - - + + fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.feature.fortran77 diff --git a/fr.cnes.icode.feature.fortran90/feature.xml b/fr.cnes.icode.feature.fortran90/feature.xml index 40ac08e2..615d7a75 100755 --- a/fr.cnes.icode.feature.fortran90/feature.xml +++ b/fr.cnes.icode.feature.fortran90/feature.xml @@ -2,7 +2,7 @@ @@ -210,8 +210,8 @@ litigation. - - + + fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.feature.fortran90 diff --git a/fr.cnes.icode.feature.shell/feature.xml b/fr.cnes.icode.feature.shell/feature.xml index 527a1e46..d179df33 100755 --- a/fr.cnes.icode.feature.shell/feature.xml +++ b/fr.cnes.icode.feature.shell/feature.xml @@ -2,7 +2,7 @@ @@ -105,8 +105,8 @@ This Agreement is governed by the laws of the State of New York and the intellec - - + + fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.feature.shell diff --git a/fr.cnes.icode.feature.ui/feature.xml b/fr.cnes.icode.feature.ui/feature.xml index 8bb80c97..1ea1fef5 100644 --- a/fr.cnes.icode.feature.ui/feature.xml +++ b/fr.cnes.icode.feature.ui/feature.xml @@ -2,7 +2,7 @@ diff --git a/fr.cnes.icode.feature.ui/pom.xml b/fr.cnes.icode.feature.ui/pom.xml index 05a7a464..ffa99f57 100644 --- a/fr.cnes.icode.feature.ui/pom.xml +++ b/fr.cnes.icode.feature.ui/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.feature.ui diff --git a/fr.cnes.icode.repository/category.xml b/fr.cnes.icode.repository/category.xml index bb5799ad..b86d8701 100755 --- a/fr.cnes.icode.repository/category.xml +++ b/fr.cnes.icode.repository/category.xml @@ -1,18 +1,18 @@ - + - + - + - + - + diff --git a/fr.cnes.icode.repository/icode.product b/fr.cnes.icode.repository/icode.product index 1c438648..22a36fa2 100644 --- a/fr.cnes.icode.repository/icode.product +++ b/fr.cnes.icode.repository/icode.product @@ -1,77 +1,77 @@ - - - - - - - - - - -consoleLog - + + + + + + + + + + -consoleLog + -Xmx1024M --Declipse.log.level=WARNING - - -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts - - - - - - - - - - - - - org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-Declipse.log.level=WARNING + + -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts + + + + + + + + + + + + + org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fr.cnes.icode.repository/icodeIDE.product b/fr.cnes.icode.repository/icodeIDE.product index 2823b48d..5d78f619 100644 --- a/fr.cnes.icode.repository/icodeIDE.product +++ b/fr.cnes.icode.repository/icodeIDE.product @@ -1,106 +1,102 @@ - - - - - - - - - - - -consoleLog - + + + + + + + + + + -consoleLog + -Xmx1024M --Declipse.log.level=WARNING - - -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts - - - - - - - - - - - - - - - org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-Declipse.log.level=WARNING + + -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts + + + + + + + + + + + + + org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fr.cnes.icode.repository/pom.xml b/fr.cnes.icode.repository/pom.xml index 66a57851..f565efc4 100644 --- a/fr.cnes.icode.repository/pom.xml +++ b/fr.cnes.icode.repository/pom.xml @@ -5,11 +5,11 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.repository - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT eclipse-repository @@ -39,7 +39,7 @@ icodeIDE.product icodeIDE - + icode.product icode icode diff --git a/fr.cnes.icode.tp/fr.cnes.icode.tp.target b/fr.cnes.icode.tp/fr.cnes.icode.tp.target index 851f9f92..2b5a4304 100644 --- a/fr.cnes.icode.tp/fr.cnes.icode.tp.target +++ b/fr.cnes.icode.tp/fr.cnes.icode.tp.target @@ -1,7 +1,7 @@ - + @@ -18,6 +18,8 @@ + + diff --git a/fr.cnes.icode.tp/fr.cnes.icode.tp.tpd b/fr.cnes.icode.tp/fr.cnes.icode.tp.tpd index 90b3a3b9..5311f6d4 100644 --- a/fr.cnes.icode.tp/fr.cnes.icode.tp.tpd +++ b/fr.cnes.icode.tp/fr.cnes.icode.tp.tpd @@ -19,9 +19,11 @@ location "http://download.eclipse.org/eclipse/updates/4.7" { org.eclipse.equinox.sdk.feature.group } -// mettre à jour suivant la target platform d'eclipse : http://download.eclipse.org/tools/orbit/downloads/ +// mettre a jour suivant la target platform d'eclipse : http://download.eclipse.org/tools/orbit/downloads/ location "http://download.eclipse.org/tools/orbit/downloads/drops/R20170919201930/repository/" { org.mockito [1.9.5,2.0.0) org.hamcrest [1.1.0,2.0.0) + org.apache.commons.cli [1.2.0,1.5.0) + org.apache.commons.io [2.0.1,2.6.0) } diff --git a/fr.cnes.icode.tp/pom.xml b/fr.cnes.icode.tp/pom.xml index 6a37c0cd..f3ae0349 100644 --- a/fr.cnes.icode.tp/pom.xml +++ b/fr.cnes.icode.tp/pom.xml @@ -5,7 +5,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.tp diff --git a/pom.xml b/pom.xml index 4a52c454..f59775eb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT pom @@ -56,6 +56,16 @@ org.mockito 0.0.0 + + eclipse-plugin + org.apache.commons.cli + 0.0.0 + + + eclipse-plugin + org.apache.commons.io + 0.0.0 + @@ -66,7 +76,6 @@ - macosx cocoa @@ -100,7 +109,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.0.1 + 3.1.0 false diff --git a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/META-INF/MANIFEST.MF index e7bb762b..ba5a6885 100644 --- a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES F77 Metrics Bundle-SymbolicName: fr.cnes.analysis.tools.fortran77.metrics.test -Bundle-Version: 3.0.1.qualifier -Fragment-Host: fr.cnes.analysis.tools.fortran77.metrics;bundle-version="3.0.1" +Bundle-Version: 3.1.0.qualifier +Fragment-Host: fr.cnes.analysis.tools.fortran77.metrics;bundle-version="3.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.mockito;bundle-version="1.8.4", org.hamcrest;bundle-version="1.1.0", diff --git a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/pom.xml b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/pom.xml index cd86ab11..185c03be 100644 --- a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/pom.xml @@ -5,7 +5,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran77.metrics.test diff --git a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/AllTests.java b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/AllTests.java index 97674394..2161415b 100755 --- a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/AllTests.java +++ b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/AllTests.java @@ -6,6 +6,7 @@ import fr.cnes.analysis.tools.fortran77.metrics.ComplexitySimplified.TestF77METComplexitySimplified; import fr.cnes.analysis.tools.fortran77.metrics.LineOfCode.TestF77METLineOfCode; +import fr.cnes.analysis.tools.fortran77.metrics.LineOfComment.TestF77METLineOfComment; import fr.cnes.analysis.tools.fortran77.metrics.Nesting.TestF77METNesting; import fr.cnes.analysis.tools.fortran77.metrics.RatioComment.TestF77METRatioComment; @@ -13,6 +14,7 @@ @SuiteClasses({TestF77METNesting.class, TestF77METComplexitySimplified.class, TestF77METLineOfCode.class, + TestF77METLineOfComment.class, TestF77METRatioComment.class}) public class AllTests { diff --git a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/LineOfComment/TestF77METLineOfComment.java b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/LineOfComment/TestF77METLineOfComment.java new file mode 100644 index 00000000..c16ef0c7 --- /dev/null +++ b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/LineOfComment/TestF77METLineOfComment.java @@ -0,0 +1,101 @@ +/************************************************************************************************/ +/** i-Code CNES is a static code analyzer. */ +/** This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/** http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ +package fr.cnes.analysis.tools.fortran77.metrics.LineOfComment; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.core.runtime.FileLocator; +import org.junit.Test; + +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.fortran77.metrics.F77METLineOfComment; +import fr.cnes.analysis.tools.fortran77.metrics.TestUtils; + +/** + * This class aims to test Don.Declaration rule. There are 2 functions in this + * class. The first one verifies that an error in a file is detected whenever + * there is one, the other verifies that nothing is detected when there's no + * error. + * + */ +public class TestF77METLineOfComment { + + /** + * This test verifies that an error can be detected. + */ + @Test + public void testRunWithError() { + + try { + // Initializing rule and getting error file. + final AbstractChecker metric = new F77METLineOfComment(); + final String fileName = "dblat2.f"; + final File file = new File( + FileLocator.resolve(this.getClass().getResource(fileName)).getFile()); + + // Defining file in the rule instantiation. + metric.setContribution(TestUtils.getContribution("", "")); + metric.setInputFile(file); + + // File Value + final List checkResults = metric.run(); + CheckResult fileValue = null; + for (CheckResult check : checkResults) { + if (check.getLocation()==null || check.getLocation().isEmpty()) { + fileValue = check; + checkResults.remove(checkResults.indexOf(check)); + } + } + + if (fileValue == null) { + fail("Erreur : Aucun r�sultat sur le fichier trouv�."); + } else { + Float exceptedFileValue = (float) 843.0; + assertTrue("Test except a file value of ["+exceptedFileValue +"] while metric computed ["+Math.round(fileValue.getValue())+"].", fileValue.getValue().equals(exceptedFileValue)); + final List functionValues = checkResults; + Map exceptedValues = new TreeMap<>(); + exceptedValues.put("FUNCTION DBEG",(float)25.0); + exceptedValues.put("FUNCTION DDIFF",(float)11.0); + exceptedValues.put("FUNCTION LDE",(float)16.0); + exceptedValues.put("FUNCTION LDERES",(float)19.0); + exceptedValues.put("PROGRAM DBLAT2",(float)73.0); + exceptedValues.put("SUBROUTINE CHKXER",(float)15.0); + exceptedValues.put("SUBROUTINE DCHK1",(float)86.0); + exceptedValues.put("SUBROUTINE DCHK2",(float)82.0); + exceptedValues.put("SUBROUTINE DCHK3",(float)79.0); + exceptedValues.put("SUBROUTINE DCHK4",(float)76.0); + exceptedValues.put("SUBROUTINE DCHK5",(float)71.0); + exceptedValues.put("SUBROUTINE DCHK6",(float)76.0); + exceptedValues.put("SUBROUTINE DCHKE",(float)27.0); + exceptedValues.put("SUBROUTINE DMAKE",(float)30.0); + exceptedValues.put("SUBROUTINE DMVCH",(float)31.0); + exceptedValues.put("SUBROUTINE XERBLA",(float)24.0); + + for(CheckResult metricValue : functionValues){ + assertTrue("Test do not excepts function : "+metricValue.getLocation()+".",exceptedValues.containsKey(metricValue.getLocation())); + assertTrue("Test excepts value of ["+Math.round(exceptedValues.get(metricValue.getLocation()))+"] while metric computed ["+Math.round(metricValue.getValue())+"] for the function "+metricValue.getLocation()+".",Math.round(metricValue.getValue()) == Math.round(exceptedValues.get(metricValue.getLocation()))); + } + assertTrue("Test excepts "+exceptedValues.size()+" functions computed for the file while the metric computed ["+functionValues.size()+"].",functionValues.size() == exceptedValues.size()); + } + } catch (final FileNotFoundException e) { + fail("Erreur d'analyse (FileNotFoundException)"); + } catch (final IOException e) { + fail("Erreur d'analyse (IOException)"); + } catch (final JFlexException e) { + fail("Erreur d'analyse (JFlexException)"); + } + } +} diff --git a/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/LineOfComment/dblat2.f b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/LineOfComment/dblat2.f new file mode 100644 index 00000000..0fa80afa --- /dev/null +++ b/tests/fr.cnes.analysis.tools.fortran77.metrics.test/src/fr/cnes/analysis/tools/fortran77/metrics/LineOfComment/dblat2.f @@ -0,0 +1,3176 @@ +*> \brief \b DBLAT2 +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* PROGRAM DBLAT2 +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Test program for the DOUBLE PRECISION Level 2 Blas. +*> +*> The program must be driven by a short data file. The first 18 records +*> of the file are read using list-directed input, the last 16 records +*> are read using the format ( A6, L2 ). An annotated example of a data +*> file can be obtained by deleting the first 3 characters from the +*> following 34 lines: +*> 'dblat2.out' NAME OF SUMMARY OUTPUT FILE +*> 6 UNIT NUMBER OF SUMMARY FILE +*> 'DBLAT2.SNAP' NAME OF SNAPSHOT OUTPUT FILE +*> -1 UNIT NUMBER OF SNAPSHOT FILE (NOT USED IF .LT. 0) +*> F LOGICAL FLAG, T TO REWIND SNAPSHOT FILE AFTER EACH RECORD. +*> F LOGICAL FLAG, T TO STOP ON FAILURES. +*> T LOGICAL FLAG, T TO TEST ERROR EXITS. +*> 16.0 THRESHOLD VALUE OF TEST RATIO +*> 6 NUMBER OF VALUES OF N +*> 0 1 2 3 5 9 VALUES OF N +*> 4 NUMBER OF VALUES OF K +*> 0 1 2 4 VALUES OF K +*> 4 NUMBER OF VALUES OF INCX AND INCY +*> 1 2 -1 -2 VALUES OF INCX AND INCY +*> 3 NUMBER OF VALUES OF ALPHA +*> 0.0 1.0 0.7 VALUES OF ALPHA +*> 3 NUMBER OF VALUES OF BETA +*> 0.0 1.0 0.9 VALUES OF BETAC +*> DGEMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DGBMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DSYMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DSBMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DSPMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DTRMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DTBMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DTPMV T PUT F FOR NO TEST. SAME COLUMNS. +*> DTRSV T PUT F FOR NO TEST. SAME COLUMNS. +*> DTBSV T PUT F FOR NO TEST. SAME COLUMNS. +*> DTPSV T PUT F FOR NO TEST. SAME COLUMNS. +*> DGER T PUT F FOR NO TEST. SAME COLUMNS. +*> DSYR T PUT F FOR NO TEST. SAME COLUMNS. +*> DSPR T PUT F FOR NO TEST. SAME COLUMNS. +*> DSYR2 T PUT F FOR NO TEST. SAME COLUMNS. +*> DSPR2 T PUT F FOR NO TEST. SAME COLUMNS. +*> +*> Further Details +*> =============== +*> +*> See: +*> +*> Dongarra J. J., Du Croz J. J., Hammarling S. and Hanson R. J.. +*> An extended set of Fortran Basic Linear Algebra Subprograms. +*> +*> Technical Memoranda Nos. 41 (revision 3) and 81, Mathematics +*> and Computer Science Division, Argonne National Laboratory, +*> 9700 South Cass Avenue, Argonne, Illinois 60439, US. +*> +*> Or +*> +*> NAG Technical Reports TR3/87 and TR4/87, Numerical Algorithms +*> Group Ltd., NAG Central Office, 256 Banbury Road, Oxford +*> OX2 7DE, UK, and Numerical Algorithms Group Inc., 1101 31st +*> Street, Suite 100, Downers Grove, Illinois 60515-1263, USA. +*> +*> +*> -- Written on 10-August-1987. +*> Richard Hanson, Sandia National Labs. +*> Jeremy Du Croz, NAG Central Office. +*> +*> 10-9-00: Change STATUS='NEW' to 'UNKNOWN' so that the testers +*> can be run multiple times without deleting generated +*> output files (susan) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date April 2012 +* +*> \ingroup double_blas_testing +* +* ===================================================================== + PROGRAM DBLAT2 +* +* -- Reference BLAS test routine (version 3.4.1) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* April 2012 +* +* ===================================================================== +* +* .. Parameters .. + INTEGER NIN + PARAMETER ( NIN = 5 ) + INTEGER NSUBS + PARAMETER ( NSUBS = 16 ) + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) + INTEGER NMAX, INCMAX + PARAMETER ( NMAX = 65, INCMAX = 2 ) + INTEGER NINMAX, NIDMAX, NKBMAX, NALMAX, NBEMAX + PARAMETER ( NINMAX = 7, NIDMAX = 9, NKBMAX = 7, + $ NALMAX = 7, NBEMAX = 7 ) +* .. Local Scalars .. + DOUBLE PRECISION EPS, ERR, THRESH + INTEGER I, ISNUM, J, N, NALF, NBET, NIDIM, NINC, NKB, + $ NOUT, NTRA + LOGICAL FATAL, LTESTT, REWI, SAME, SFATAL, TRACE, + $ TSTERR + CHARACTER*1 TRANS + CHARACTER*6 SNAMET + CHARACTER*32 SNAPS, SUMMRY +* .. Local Arrays .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), + $ ALF( NALMAX ), AS( NMAX*NMAX ), BET( NBEMAX ), + $ G( NMAX ), X( NMAX ), XS( NMAX*INCMAX ), + $ XX( NMAX*INCMAX ), Y( NMAX ), + $ YS( NMAX*INCMAX ), YT( NMAX ), + $ YY( NMAX*INCMAX ), Z( 2*NMAX ) + INTEGER IDIM( NIDMAX ), INC( NINMAX ), KB( NKBMAX ) + LOGICAL LTEST( NSUBS ) + CHARACTER*6 SNAMES( NSUBS ) +* .. External Functions .. + DOUBLE PRECISION DDIFF + LOGICAL LDE + EXTERNAL DDIFF, LDE +* .. External Subroutines .. + EXTERNAL DCHK1, DCHK2, DCHK3, DCHK4, DCHK5, DCHK6, + $ DCHKE, DMVCH +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK + CHARACTER*6 SRNAMT +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR + COMMON /SRNAMC/SRNAMT +* .. Data statements .. + DATA SNAMES/'DGEMV ', 'DGBMV ', 'DSYMV ', 'DSBMV ', + $ 'DSPMV ', 'DTRMV ', 'DTBMV ', 'DTPMV ', + $ 'DTRSV ', 'DTBSV ', 'DTPSV ', 'DGER ', + $ 'DSYR ', 'DSPR ', 'DSYR2 ', 'DSPR2 '/ +* .. Executable Statements .. +* +* Read name and unit number for summary output file and open file. +* + READ( NIN, FMT = * )SUMMRY + READ( NIN, FMT = * )NOUT + OPEN( NOUT, FILE = SUMMRY, STATUS = 'UNKNOWN' ) + NOUTC = NOUT +* +* Read name and unit number for snapshot output file and open file. +* + READ( NIN, FMT = * )SNAPS + READ( NIN, FMT = * )NTRA + TRACE = NTRA.GE.0 + IF( TRACE )THEN + OPEN( NTRA, FILE = SNAPS, STATUS = 'UNKNOWN' ) + END IF +* Read the flag that directs rewinding of the snapshot file. + READ( NIN, FMT = * )REWI + REWI = REWI.AND.TRACE +* Read the flag that directs stopping on any failure. + READ( NIN, FMT = * )SFATAL +* Read the flag that indicates whether error exits are to be tested. + READ( NIN, FMT = * )TSTERR +* Read the threshold value of the test ratio + READ( NIN, FMT = * )THRESH +* +* Read and check the parameter values for the tests. +* +* Values of N + READ( NIN, FMT = * )NIDIM + IF( NIDIM.LT.1.OR.NIDIM.GT.NIDMAX )THEN + WRITE( NOUT, FMT = 9997 )'N', NIDMAX + GO TO 230 + END IF + READ( NIN, FMT = * )( IDIM( I ), I = 1, NIDIM ) + DO 10 I = 1, NIDIM + IF( IDIM( I ).LT.0.OR.IDIM( I ).GT.NMAX )THEN + WRITE( NOUT, FMT = 9996 )NMAX + GO TO 230 + END IF + 10 CONTINUE +* Values of K + READ( NIN, FMT = * )NKB + IF( NKB.LT.1.OR.NKB.GT.NKBMAX )THEN + WRITE( NOUT, FMT = 9997 )'K', NKBMAX + GO TO 230 + END IF + READ( NIN, FMT = * )( KB( I ), I = 1, NKB ) + DO 20 I = 1, NKB + IF( KB( I ).LT.0 )THEN + WRITE( NOUT, FMT = 9995 ) + GO TO 230 + END IF + 20 CONTINUE +* Values of INCX and INCY + READ( NIN, FMT = * )NINC + IF( NINC.LT.1.OR.NINC.GT.NINMAX )THEN + WRITE( NOUT, FMT = 9997 )'INCX AND INCY', NINMAX + GO TO 230 + END IF + READ( NIN, FMT = * )( INC( I ), I = 1, NINC ) + DO 30 I = 1, NINC + IF( INC( I ).EQ.0.OR.ABS( INC( I ) ).GT.INCMAX )THEN + WRITE( NOUT, FMT = 9994 )INCMAX + GO TO 230 + END IF + 30 CONTINUE +* Values of ALPHA + READ( NIN, FMT = * )NALF + IF( NALF.LT.1.OR.NALF.GT.NALMAX )THEN + WRITE( NOUT, FMT = 9997 )'ALPHA', NALMAX + GO TO 230 + END IF + READ( NIN, FMT = * )( ALF( I ), I = 1, NALF ) +* Values of BETA + READ( NIN, FMT = * )NBET + IF( NBET.LT.1.OR.NBET.GT.NBEMAX )THEN + WRITE( NOUT, FMT = 9997 )'BETA', NBEMAX + GO TO 230 + END IF + READ( NIN, FMT = * )( BET( I ), I = 1, NBET ) +* +* Report values of parameters. +* + WRITE( NOUT, FMT = 9993 ) + WRITE( NOUT, FMT = 9992 )( IDIM( I ), I = 1, NIDIM ) + WRITE( NOUT, FMT = 9991 )( KB( I ), I = 1, NKB ) + WRITE( NOUT, FMT = 9990 )( INC( I ), I = 1, NINC ) + WRITE( NOUT, FMT = 9989 )( ALF( I ), I = 1, NALF ) + WRITE( NOUT, FMT = 9988 )( BET( I ), I = 1, NBET ) + IF( .NOT.TSTERR )THEN + WRITE( NOUT, FMT = * ) + WRITE( NOUT, FMT = 9980 ) + END IF + WRITE( NOUT, FMT = * ) + WRITE( NOUT, FMT = 9999 )THRESH + WRITE( NOUT, FMT = * ) +* +* Read names of subroutines and flags which indicate +* whether they are to be tested. +* + DO 40 I = 1, NSUBS + LTEST( I ) = .FALSE. + 40 CONTINUE + 50 READ( NIN, FMT = 9984, END = 80 )SNAMET, LTESTT + DO 60 I = 1, NSUBS + IF( SNAMET.EQ.SNAMES( I ) ) + $ GO TO 70 + 60 CONTINUE + WRITE( NOUT, FMT = 9986 )SNAMET + STOP + 70 LTEST( I ) = LTESTT + GO TO 50 +* + 80 CONTINUE + CLOSE ( NIN ) +* +* Compute EPS (the machine precision). +* + EPS = EPSILON(ZERO) + WRITE( NOUT, FMT = 9998 )EPS +* +* Check the reliability of DMVCH using exact data. +* + N = MIN( 32, NMAX ) + DO 120 J = 1, N + DO 110 I = 1, N + A( I, J ) = MAX( I - J + 1, 0 ) + 110 CONTINUE + X( J ) = J + Y( J ) = ZERO + 120 CONTINUE + DO 130 J = 1, N + YY( J ) = J*( ( J + 1 )*J )/2 - ( ( J + 1 )*J*( J - 1 ) )/3 + 130 CONTINUE +* YY holds the exact result. On exit from DMVCH YT holds +* the result computed by DMVCH. + TRANS = 'N' + CALL DMVCH( TRANS, N, N, ONE, A, NMAX, X, 1, ZERO, Y, 1, YT, G, + $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) + SAME = LDE( YY, YT, N ) + IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN + WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR + STOP + END IF + TRANS = 'T' + CALL DMVCH( TRANS, N, N, ONE, A, NMAX, X, -1, ZERO, Y, -1, YT, G, + $ YY, EPS, ERR, FATAL, NOUT, .TRUE. ) + SAME = LDE( YY, YT, N ) + IF( .NOT.SAME.OR.ERR.NE.ZERO )THEN + WRITE( NOUT, FMT = 9985 )TRANS, SAME, ERR + STOP + END IF +* +* Test each subroutine in turn. +* + DO 210 ISNUM = 1, NSUBS + WRITE( NOUT, FMT = * ) + IF( .NOT.LTEST( ISNUM ) )THEN +* Subprogram is not to be tested. + WRITE( NOUT, FMT = 9983 )SNAMES( ISNUM ) + ELSE + SRNAMT = SNAMES( ISNUM ) +* Test error exits. + IF( TSTERR )THEN + CALL DCHKE( ISNUM, SNAMES( ISNUM ), NOUT ) + WRITE( NOUT, FMT = * ) + END IF +* Test computations. + INFOT = 0 + OK = .TRUE. + FATAL = .FALSE. + GO TO ( 140, 140, 150, 150, 150, 160, 160, + $ 160, 160, 160, 160, 170, 180, 180, + $ 190, 190 )ISNUM +* Test DGEMV, 01, and DGBMV, 02. + 140 CALL DCHK1( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, + $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, + $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, + $ X, XX, XS, Y, YY, YS, YT, G ) + GO TO 200 +* Test DSYMV, 03, DSBMV, 04, and DSPMV, 05. + 150 CALL DCHK2( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, + $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, + $ NBET, BET, NINC, INC, NMAX, INCMAX, A, AA, AS, + $ X, XX, XS, Y, YY, YS, YT, G ) + GO TO 200 +* Test DTRMV, 06, DTBMV, 07, DTPMV, 08, +* DTRSV, 09, DTBSV, 10, and DTPSV, 11. + 160 CALL DCHK3( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, + $ REWI, FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, + $ NMAX, INCMAX, A, AA, AS, Y, YY, YS, YT, G, Z ) + GO TO 200 +* Test DGER, 12. + 170 CALL DCHK4( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, + $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, + $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, + $ YT, G, Z ) + GO TO 200 +* Test DSYR, 13, and DSPR, 14. + 180 CALL DCHK5( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, + $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, + $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, + $ YT, G, Z ) + GO TO 200 +* Test DSYR2, 15, and DSPR2, 16. + 190 CALL DCHK6( SNAMES( ISNUM ), EPS, THRESH, NOUT, NTRA, TRACE, + $ REWI, FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, + $ NMAX, INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, + $ YT, G, Z ) +* + 200 IF( FATAL.AND.SFATAL ) + $ GO TO 220 + END IF + 210 CONTINUE + WRITE( NOUT, FMT = 9982 ) + GO TO 240 +* + 220 CONTINUE + WRITE( NOUT, FMT = 9981 ) + GO TO 240 +* + 230 CONTINUE + WRITE( NOUT, FMT = 9987 ) +* + 240 CONTINUE + IF( TRACE ) + $ CLOSE ( NTRA ) + CLOSE ( NOUT ) + STOP +* + 9999 FORMAT( ' ROUTINES PASS COMPUTATIONAL TESTS IF TEST RATIO IS LES', + $ 'S THAN', F8.2 ) + 9998 FORMAT( ' RELATIVE MACHINE PRECISION IS TAKEN TO BE', 1P, D9.1 ) + 9997 FORMAT( ' NUMBER OF VALUES OF ', A, ' IS LESS THAN 1 OR GREATER ', + $ 'THAN ', I2 ) + 9996 FORMAT( ' VALUE OF N IS LESS THAN 0 OR GREATER THAN ', I2 ) + 9995 FORMAT( ' VALUE OF K IS LESS THAN 0' ) + 9994 FORMAT( ' ABSOLUTE VALUE OF INCX OR INCY IS 0 OR GREATER THAN ', + $ I2 ) + 9993 FORMAT( ' TESTS OF THE DOUBLE PRECISION LEVEL 2 BLAS', //' THE F', + $ 'OLLOWING PARAMETER VALUES WILL BE USED:' ) + 9992 FORMAT( ' FOR N ', 9I6 ) + 9991 FORMAT( ' FOR K ', 7I6 ) + 9990 FORMAT( ' FOR INCX AND INCY ', 7I6 ) + 9989 FORMAT( ' FOR ALPHA ', 7F6.1 ) + 9988 FORMAT( ' FOR BETA ', 7F6.1 ) + 9987 FORMAT( ' AMEND DATA FILE OR INCREASE ARRAY SIZES IN PROGRAM', + $ /' ******* TESTS ABANDONED *******' ) + 9986 FORMAT( ' SUBPROGRAM NAME ', A6, ' NOT RECOGNIZED', /' ******* T', + $ 'ESTS ABANDONED *******' ) + 9985 FORMAT( ' ERROR IN DMVCH - IN-LINE DOT PRODUCTS ARE BEING EVALU', + $ 'ATED WRONGLY.', /' DMVCH WAS CALLED WITH TRANS = ', A1, + $ ' AND RETURNED SAME = ', L1, ' AND ERR = ', F12.3, '.', / + $ ' THIS MAY BE DUE TO FAULTS IN THE ARITHMETIC OR THE COMPILER.' + $ , /' ******* TESTS ABANDONED *******' ) + 9984 FORMAT( A6, L2 ) + 9983 FORMAT( 1X, A6, ' WAS NOT TESTED' ) + 9982 FORMAT( /' END OF TESTS' ) + 9981 FORMAT( /' ******* FATAL ERROR - TESTS ABANDONED *******' ) + 9980 FORMAT( ' ERROR-EXITS WILL NOT BE TESTED' ) +* +* End of DBLAT2. +* + END + SUBROUTINE DCHK1( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, + $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, + $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, + $ XS, Y, YY, YS, YT, G ) +* +* Tests DGEMV and DGBMV. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION EPS, THRESH + INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, + $ NOUT, NTRA + LOGICAL FATAL, REWI, TRACE + CHARACTER*6 SNAME +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), + $ AS( NMAX*NMAX ), BET( NBET ), G( NMAX ), + $ X( NMAX ), XS( NMAX*INCMAX ), + $ XX( NMAX*INCMAX ), Y( NMAX ), + $ YS( NMAX*INCMAX ), YT( NMAX ), + $ YY( NMAX*INCMAX ) + INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, ALS, BETA, BLS, ERR, ERRMAX, TRANSL + INTEGER I, IA, IB, IC, IKU, IM, IN, INCX, INCXS, INCY, + $ INCYS, IX, IY, KL, KLS, KU, KUS, LAA, LDA, + $ LDAS, LX, LY, M, ML, MS, N, NARGS, NC, ND, NK, + $ NL, NS + LOGICAL BANDED, FULL, NULL, RESET, SAME, TRAN + CHARACTER*1 TRANS, TRANSS + CHARACTER*3 ICH +* .. Local Arrays .. + LOGICAL ISAME( 13 ) +* .. External Functions .. + LOGICAL LDE, LDERES + EXTERNAL LDE, LDERES +* .. External Subroutines .. + EXTERNAL DGBMV, DGEMV, DMAKE, DMVCH +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Data statements .. + DATA ICH/'NTC'/ +* .. Executable Statements .. + FULL = SNAME( 3: 3 ).EQ.'E' + BANDED = SNAME( 3: 3 ).EQ.'B' +* Define the number of arguments. + IF( FULL )THEN + NARGS = 11 + ELSE IF( BANDED )THEN + NARGS = 13 + END IF +* + NC = 0 + RESET = .TRUE. + ERRMAX = ZERO +* + DO 120 IN = 1, NIDIM + N = IDIM( IN ) + ND = N/2 + 1 +* + DO 110 IM = 1, 2 + IF( IM.EQ.1 ) + $ M = MAX( N - ND, 0 ) + IF( IM.EQ.2 ) + $ M = MIN( N + ND, NMAX ) +* + IF( BANDED )THEN + NK = NKB + ELSE + NK = 1 + END IF + DO 100 IKU = 1, NK + IF( BANDED )THEN + KU = KB( IKU ) + KL = MAX( KU - 1, 0 ) + ELSE + KU = N - 1 + KL = M - 1 + END IF +* Set LDA to 1 more than minimum value if room. + IF( BANDED )THEN + LDA = KL + KU + 1 + ELSE + LDA = M + END IF + IF( LDA.LT.NMAX ) + $ LDA = LDA + 1 +* Skip tests if not enough room. + IF( LDA.GT.NMAX ) + $ GO TO 100 + LAA = LDA*N + NULL = N.LE.0.OR.M.LE.0 +* +* Generate the matrix A. +* + TRANSL = ZERO + CALL DMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, AA, + $ LDA, KL, KU, RESET, TRANSL ) +* + DO 90 IC = 1, 3 + TRANS = ICH( IC: IC ) + TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' +* + IF( TRAN )THEN + ML = N + NL = M + ELSE + ML = M + NL = N + END IF +* + DO 80 IX = 1, NINC + INCX = INC( IX ) + LX = ABS( INCX )*NL +* +* Generate the vector X. +* + TRANSL = HALF + CALL DMAKE( 'GE', ' ', ' ', 1, NL, X, 1, XX, + $ ABS( INCX ), 0, NL - 1, RESET, TRANSL ) + IF( NL.GT.1 )THEN + X( NL/2 ) = ZERO + XX( 1 + ABS( INCX )*( NL/2 - 1 ) ) = ZERO + END IF +* + DO 70 IY = 1, NINC + INCY = INC( IY ) + LY = ABS( INCY )*ML +* + DO 60 IA = 1, NALF + ALPHA = ALF( IA ) +* + DO 50 IB = 1, NBET + BETA = BET( IB ) +* +* Generate the vector Y. +* + TRANSL = ZERO + CALL DMAKE( 'GE', ' ', ' ', 1, ML, Y, 1, + $ YY, ABS( INCY ), 0, ML - 1, + $ RESET, TRANSL ) +* + NC = NC + 1 +* +* Save every datum before calling the +* subroutine. +* + TRANSS = TRANS + MS = M + NS = N + KLS = KL + KUS = KU + ALS = ALPHA + DO 10 I = 1, LAA + AS( I ) = AA( I ) + 10 CONTINUE + LDAS = LDA + DO 20 I = 1, LX + XS( I ) = XX( I ) + 20 CONTINUE + INCXS = INCX + BLS = BETA + DO 30 I = 1, LY + YS( I ) = YY( I ) + 30 CONTINUE + INCYS = INCY +* +* Call the subroutine. +* + IF( FULL )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, + $ TRANS, M, N, ALPHA, LDA, INCX, BETA, + $ INCY + IF( REWI ) + $ REWIND NTRA + CALL DGEMV( TRANS, M, N, ALPHA, AA, + $ LDA, XX, INCX, BETA, YY, + $ INCY ) + ELSE IF( BANDED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9995 )NC, SNAME, + $ TRANS, M, N, KL, KU, ALPHA, LDA, + $ INCX, BETA, INCY + IF( REWI ) + $ REWIND NTRA + CALL DGBMV( TRANS, M, N, KL, KU, ALPHA, + $ AA, LDA, XX, INCX, BETA, + $ YY, INCY ) + END IF +* +* Check if error-exit was taken incorrectly. +* + IF( .NOT.OK )THEN + WRITE( NOUT, FMT = 9993 ) + FATAL = .TRUE. + GO TO 130 + END IF +* +* See what data changed inside subroutines. +* + ISAME( 1 ) = TRANS.EQ.TRANSS + ISAME( 2 ) = MS.EQ.M + ISAME( 3 ) = NS.EQ.N + IF( FULL )THEN + ISAME( 4 ) = ALS.EQ.ALPHA + ISAME( 5 ) = LDE( AS, AA, LAA ) + ISAME( 6 ) = LDAS.EQ.LDA + ISAME( 7 ) = LDE( XS, XX, LX ) + ISAME( 8 ) = INCXS.EQ.INCX + ISAME( 9 ) = BLS.EQ.BETA + IF( NULL )THEN + ISAME( 10 ) = LDE( YS, YY, LY ) + ELSE + ISAME( 10 ) = LDERES( 'GE', ' ', 1, + $ ML, YS, YY, + $ ABS( INCY ) ) + END IF + ISAME( 11 ) = INCYS.EQ.INCY + ELSE IF( BANDED )THEN + ISAME( 4 ) = KLS.EQ.KL + ISAME( 5 ) = KUS.EQ.KU + ISAME( 6 ) = ALS.EQ.ALPHA + ISAME( 7 ) = LDE( AS, AA, LAA ) + ISAME( 8 ) = LDAS.EQ.LDA + ISAME( 9 ) = LDE( XS, XX, LX ) + ISAME( 10 ) = INCXS.EQ.INCX + ISAME( 11 ) = BLS.EQ.BETA + IF( NULL )THEN + ISAME( 12 ) = LDE( YS, YY, LY ) + ELSE + ISAME( 12 ) = LDERES( 'GE', ' ', 1, + $ ML, YS, YY, + $ ABS( INCY ) ) + END IF + ISAME( 13 ) = INCYS.EQ.INCY + END IF +* +* If data was incorrectly changed, report +* and return. +* + SAME = .TRUE. + DO 40 I = 1, NARGS + SAME = SAME.AND.ISAME( I ) + IF( .NOT.ISAME( I ) ) + $ WRITE( NOUT, FMT = 9998 )I + 40 CONTINUE + IF( .NOT.SAME )THEN + FATAL = .TRUE. + GO TO 130 + END IF +* + IF( .NOT.NULL )THEN +* +* Check the result. +* + CALL DMVCH( TRANS, M, N, ALPHA, A, + $ NMAX, X, INCX, BETA, Y, + $ INCY, YT, G, YY, EPS, ERR, + $ FATAL, NOUT, .TRUE. ) + ERRMAX = MAX( ERRMAX, ERR ) +* If got really bad answer, report and +* return. + IF( FATAL ) + $ GO TO 130 + ELSE +* Avoid repeating tests with M.le.0 or +* N.le.0. + GO TO 110 + END IF +* + 50 CONTINUE +* + 60 CONTINUE +* + 70 CONTINUE +* + 80 CONTINUE +* + 90 CONTINUE +* + 100 CONTINUE +* + 110 CONTINUE +* + 120 CONTINUE +* +* Report result. +* + IF( ERRMAX.LT.THRESH )THEN + WRITE( NOUT, FMT = 9999 )SNAME, NC + ELSE + WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX + END IF + GO TO 140 +* + 130 CONTINUE + WRITE( NOUT, FMT = 9996 )SNAME + IF( FULL )THEN + WRITE( NOUT, FMT = 9994 )NC, SNAME, TRANS, M, N, ALPHA, LDA, + $ INCX, BETA, INCY + ELSE IF( BANDED )THEN + WRITE( NOUT, FMT = 9995 )NC, SNAME, TRANS, M, N, KL, KU, + $ ALPHA, LDA, INCX, BETA, INCY + END IF +* + 140 CONTINUE + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', + $ 'S)' ) + 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', + $ 'ANGED INCORRECTLY *******' ) + 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', + $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, + $ ' - SUSPECT *******' ) + 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) + 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 4( I3, ',' ), F4.1, + $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) + 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), F4.1, + $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, + $ ') .' ) + 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', + $ '******' ) +* +* End of DCHK1. +* + END + SUBROUTINE DCHK2( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, + $ FATAL, NIDIM, IDIM, NKB, KB, NALF, ALF, NBET, + $ BET, NINC, INC, NMAX, INCMAX, A, AA, AS, X, XX, + $ XS, Y, YY, YS, YT, G ) +* +* Tests DSYMV, DSBMV and DSPMV. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION EPS, THRESH + INTEGER INCMAX, NALF, NBET, NIDIM, NINC, NKB, NMAX, + $ NOUT, NTRA + LOGICAL FATAL, REWI, TRACE + CHARACTER*6 SNAME +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), + $ AS( NMAX*NMAX ), BET( NBET ), G( NMAX ), + $ X( NMAX ), XS( NMAX*INCMAX ), + $ XX( NMAX*INCMAX ), Y( NMAX ), + $ YS( NMAX*INCMAX ), YT( NMAX ), + $ YY( NMAX*INCMAX ) + INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, ALS, BETA, BLS, ERR, ERRMAX, TRANSL + INTEGER I, IA, IB, IC, IK, IN, INCX, INCXS, INCY, + $ INCYS, IX, IY, K, KS, LAA, LDA, LDAS, LX, LY, + $ N, NARGS, NC, NK, NS + LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME + CHARACTER*1 UPLO, UPLOS + CHARACTER*2 ICH +* .. Local Arrays .. + LOGICAL ISAME( 13 ) +* .. External Functions .. + LOGICAL LDE, LDERES + EXTERNAL LDE, LDERES +* .. External Subroutines .. + EXTERNAL DMAKE, DMVCH, DSBMV, DSPMV, DSYMV +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Data statements .. + DATA ICH/'UL'/ +* .. Executable Statements .. + FULL = SNAME( 3: 3 ).EQ.'Y' + BANDED = SNAME( 3: 3 ).EQ.'B' + PACKED = SNAME( 3: 3 ).EQ.'P' +* Define the number of arguments. + IF( FULL )THEN + NARGS = 10 + ELSE IF( BANDED )THEN + NARGS = 11 + ELSE IF( PACKED )THEN + NARGS = 9 + END IF +* + NC = 0 + RESET = .TRUE. + ERRMAX = ZERO +* + DO 110 IN = 1, NIDIM + N = IDIM( IN ) +* + IF( BANDED )THEN + NK = NKB + ELSE + NK = 1 + END IF + DO 100 IK = 1, NK + IF( BANDED )THEN + K = KB( IK ) + ELSE + K = N - 1 + END IF +* Set LDA to 1 more than minimum value if room. + IF( BANDED )THEN + LDA = K + 1 + ELSE + LDA = N + END IF + IF( LDA.LT.NMAX ) + $ LDA = LDA + 1 +* Skip tests if not enough room. + IF( LDA.GT.NMAX ) + $ GO TO 100 + IF( PACKED )THEN + LAA = ( N*( N + 1 ) )/2 + ELSE + LAA = LDA*N + END IF + NULL = N.LE.0 +* + DO 90 IC = 1, 2 + UPLO = ICH( IC: IC ) +* +* Generate the matrix A. +* + TRANSL = ZERO + CALL DMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, AA, + $ LDA, K, K, RESET, TRANSL ) +* + DO 80 IX = 1, NINC + INCX = INC( IX ) + LX = ABS( INCX )*N +* +* Generate the vector X. +* + TRANSL = HALF + CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, + $ ABS( INCX ), 0, N - 1, RESET, TRANSL ) + IF( N.GT.1 )THEN + X( N/2 ) = ZERO + XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO + END IF +* + DO 70 IY = 1, NINC + INCY = INC( IY ) + LY = ABS( INCY )*N +* + DO 60 IA = 1, NALF + ALPHA = ALF( IA ) +* + DO 50 IB = 1, NBET + BETA = BET( IB ) +* +* Generate the vector Y. +* + TRANSL = ZERO + CALL DMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, + $ ABS( INCY ), 0, N - 1, RESET, + $ TRANSL ) +* + NC = NC + 1 +* +* Save every datum before calling the +* subroutine. +* + UPLOS = UPLO + NS = N + KS = K + ALS = ALPHA + DO 10 I = 1, LAA + AS( I ) = AA( I ) + 10 CONTINUE + LDAS = LDA + DO 20 I = 1, LX + XS( I ) = XX( I ) + 20 CONTINUE + INCXS = INCX + BLS = BETA + DO 30 I = 1, LY + YS( I ) = YY( I ) + 30 CONTINUE + INCYS = INCY +* +* Call the subroutine. +* + IF( FULL )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9993 )NC, SNAME, + $ UPLO, N, ALPHA, LDA, INCX, BETA, INCY + IF( REWI ) + $ REWIND NTRA + CALL DSYMV( UPLO, N, ALPHA, AA, LDA, XX, + $ INCX, BETA, YY, INCY ) + ELSE IF( BANDED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, + $ UPLO, N, K, ALPHA, LDA, INCX, BETA, + $ INCY + IF( REWI ) + $ REWIND NTRA + CALL DSBMV( UPLO, N, K, ALPHA, AA, LDA, + $ XX, INCX, BETA, YY, INCY ) + ELSE IF( PACKED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9995 )NC, SNAME, + $ UPLO, N, ALPHA, INCX, BETA, INCY + IF( REWI ) + $ REWIND NTRA + CALL DSPMV( UPLO, N, ALPHA, AA, XX, INCX, + $ BETA, YY, INCY ) + END IF +* +* Check if error-exit was taken incorrectly. +* + IF( .NOT.OK )THEN + WRITE( NOUT, FMT = 9992 ) + FATAL = .TRUE. + GO TO 120 + END IF +* +* See what data changed inside subroutines. +* + ISAME( 1 ) = UPLO.EQ.UPLOS + ISAME( 2 ) = NS.EQ.N + IF( FULL )THEN + ISAME( 3 ) = ALS.EQ.ALPHA + ISAME( 4 ) = LDE( AS, AA, LAA ) + ISAME( 5 ) = LDAS.EQ.LDA + ISAME( 6 ) = LDE( XS, XX, LX ) + ISAME( 7 ) = INCXS.EQ.INCX + ISAME( 8 ) = BLS.EQ.BETA + IF( NULL )THEN + ISAME( 9 ) = LDE( YS, YY, LY ) + ELSE + ISAME( 9 ) = LDERES( 'GE', ' ', 1, N, + $ YS, YY, ABS( INCY ) ) + END IF + ISAME( 10 ) = INCYS.EQ.INCY + ELSE IF( BANDED )THEN + ISAME( 3 ) = KS.EQ.K + ISAME( 4 ) = ALS.EQ.ALPHA + ISAME( 5 ) = LDE( AS, AA, LAA ) + ISAME( 6 ) = LDAS.EQ.LDA + ISAME( 7 ) = LDE( XS, XX, LX ) + ISAME( 8 ) = INCXS.EQ.INCX + ISAME( 9 ) = BLS.EQ.BETA + IF( NULL )THEN + ISAME( 10 ) = LDE( YS, YY, LY ) + ELSE + ISAME( 10 ) = LDERES( 'GE', ' ', 1, N, + $ YS, YY, ABS( INCY ) ) + END IF + ISAME( 11 ) = INCYS.EQ.INCY + ELSE IF( PACKED )THEN + ISAME( 3 ) = ALS.EQ.ALPHA + ISAME( 4 ) = LDE( AS, AA, LAA ) + ISAME( 5 ) = LDE( XS, XX, LX ) + ISAME( 6 ) = INCXS.EQ.INCX + ISAME( 7 ) = BLS.EQ.BETA + IF( NULL )THEN + ISAME( 8 ) = LDE( YS, YY, LY ) + ELSE + ISAME( 8 ) = LDERES( 'GE', ' ', 1, N, + $ YS, YY, ABS( INCY ) ) + END IF + ISAME( 9 ) = INCYS.EQ.INCY + END IF +* +* If data was incorrectly changed, report and +* return. +* + SAME = .TRUE. + DO 40 I = 1, NARGS + SAME = SAME.AND.ISAME( I ) + IF( .NOT.ISAME( I ) ) + $ WRITE( NOUT, FMT = 9998 )I + 40 CONTINUE + IF( .NOT.SAME )THEN + FATAL = .TRUE. + GO TO 120 + END IF +* + IF( .NOT.NULL )THEN +* +* Check the result. +* + CALL DMVCH( 'N', N, N, ALPHA, A, NMAX, X, + $ INCX, BETA, Y, INCY, YT, G, + $ YY, EPS, ERR, FATAL, NOUT, + $ .TRUE. ) + ERRMAX = MAX( ERRMAX, ERR ) +* If got really bad answer, report and +* return. + IF( FATAL ) + $ GO TO 120 + ELSE +* Avoid repeating tests with N.le.0 + GO TO 110 + END IF +* + 50 CONTINUE +* + 60 CONTINUE +* + 70 CONTINUE +* + 80 CONTINUE +* + 90 CONTINUE +* + 100 CONTINUE +* + 110 CONTINUE +* +* Report result. +* + IF( ERRMAX.LT.THRESH )THEN + WRITE( NOUT, FMT = 9999 )SNAME, NC + ELSE + WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX + END IF + GO TO 130 +* + 120 CONTINUE + WRITE( NOUT, FMT = 9996 )SNAME + IF( FULL )THEN + WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, LDA, INCX, + $ BETA, INCY + ELSE IF( BANDED )THEN + WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, K, ALPHA, LDA, + $ INCX, BETA, INCY + ELSE IF( PACKED )THEN + WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, N, ALPHA, INCX, + $ BETA, INCY + END IF +* + 130 CONTINUE + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', + $ 'S)' ) + 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', + $ 'ANGED INCORRECTLY *******' ) + 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', + $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, + $ ' - SUSPECT *******' ) + 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) + 9995 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', AP', + $ ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) + 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', 2( I3, ',' ), F4.1, + $ ', A,', I3, ', X,', I2, ',', F4.1, ', Y,', I2, + $ ') .' ) + 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', A,', + $ I3, ', X,', I2, ',', F4.1, ', Y,', I2, ') .' ) + 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', + $ '******' ) +* +* End of DCHK2. +* + END + SUBROUTINE DCHK3( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, + $ FATAL, NIDIM, IDIM, NKB, KB, NINC, INC, NMAX, + $ INCMAX, A, AA, AS, X, XX, XS, XT, G, Z ) +* +* Tests DTRMV, DTBMV, DTPMV, DTRSV, DTBSV and DTPSV. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION EPS, THRESH + INTEGER INCMAX, NIDIM, NINC, NKB, NMAX, NOUT, NTRA + LOGICAL FATAL, REWI, TRACE + CHARACTER*6 SNAME +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), + $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), + $ XS( NMAX*INCMAX ), XT( NMAX ), + $ XX( NMAX*INCMAX ), Z( NMAX ) + INTEGER IDIM( NIDIM ), INC( NINC ), KB( NKB ) +* .. Local Scalars .. + DOUBLE PRECISION ERR, ERRMAX, TRANSL + INTEGER I, ICD, ICT, ICU, IK, IN, INCX, INCXS, IX, K, + $ KS, LAA, LDA, LDAS, LX, N, NARGS, NC, NK, NS + LOGICAL BANDED, FULL, NULL, PACKED, RESET, SAME + CHARACTER*1 DIAG, DIAGS, TRANS, TRANSS, UPLO, UPLOS + CHARACTER*2 ICHD, ICHU + CHARACTER*3 ICHT +* .. Local Arrays .. + LOGICAL ISAME( 13 ) +* .. External Functions .. + LOGICAL LDE, LDERES + EXTERNAL LDE, LDERES +* .. External Subroutines .. + EXTERNAL DMAKE, DMVCH, DTBMV, DTBSV, DTPMV, DTPSV, + $ DTRMV, DTRSV +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Data statements .. + DATA ICHU/'UL'/, ICHT/'NTC'/, ICHD/'UN'/ +* .. Executable Statements .. + FULL = SNAME( 3: 3 ).EQ.'R' + BANDED = SNAME( 3: 3 ).EQ.'B' + PACKED = SNAME( 3: 3 ).EQ.'P' +* Define the number of arguments. + IF( FULL )THEN + NARGS = 8 + ELSE IF( BANDED )THEN + NARGS = 9 + ELSE IF( PACKED )THEN + NARGS = 7 + END IF +* + NC = 0 + RESET = .TRUE. + ERRMAX = ZERO +* Set up zero vector for DMVCH. + DO 10 I = 1, NMAX + Z( I ) = ZERO + 10 CONTINUE +* + DO 110 IN = 1, NIDIM + N = IDIM( IN ) +* + IF( BANDED )THEN + NK = NKB + ELSE + NK = 1 + END IF + DO 100 IK = 1, NK + IF( BANDED )THEN + K = KB( IK ) + ELSE + K = N - 1 + END IF +* Set LDA to 1 more than minimum value if room. + IF( BANDED )THEN + LDA = K + 1 + ELSE + LDA = N + END IF + IF( LDA.LT.NMAX ) + $ LDA = LDA + 1 +* Skip tests if not enough room. + IF( LDA.GT.NMAX ) + $ GO TO 100 + IF( PACKED )THEN + LAA = ( N*( N + 1 ) )/2 + ELSE + LAA = LDA*N + END IF + NULL = N.LE.0 +* + DO 90 ICU = 1, 2 + UPLO = ICHU( ICU: ICU ) +* + DO 80 ICT = 1, 3 + TRANS = ICHT( ICT: ICT ) +* + DO 70 ICD = 1, 2 + DIAG = ICHD( ICD: ICD ) +* +* Generate the matrix A. +* + TRANSL = ZERO + CALL DMAKE( SNAME( 2: 3 ), UPLO, DIAG, N, N, A, + $ NMAX, AA, LDA, K, K, RESET, TRANSL ) +* + DO 60 IX = 1, NINC + INCX = INC( IX ) + LX = ABS( INCX )*N +* +* Generate the vector X. +* + TRANSL = HALF + CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, + $ ABS( INCX ), 0, N - 1, RESET, + $ TRANSL ) + IF( N.GT.1 )THEN + X( N/2 ) = ZERO + XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO + END IF +* + NC = NC + 1 +* +* Save every datum before calling the subroutine. +* + UPLOS = UPLO + TRANSS = TRANS + DIAGS = DIAG + NS = N + KS = K + DO 20 I = 1, LAA + AS( I ) = AA( I ) + 20 CONTINUE + LDAS = LDA + DO 30 I = 1, LX + XS( I ) = XX( I ) + 30 CONTINUE + INCXS = INCX +* +* Call the subroutine. +* + IF( SNAME( 4: 5 ).EQ.'MV' )THEN + IF( FULL )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9993 )NC, SNAME, + $ UPLO, TRANS, DIAG, N, LDA, INCX + IF( REWI ) + $ REWIND NTRA + CALL DTRMV( UPLO, TRANS, DIAG, N, AA, LDA, + $ XX, INCX ) + ELSE IF( BANDED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, + $ UPLO, TRANS, DIAG, N, K, LDA, INCX + IF( REWI ) + $ REWIND NTRA + CALL DTBMV( UPLO, TRANS, DIAG, N, K, AA, + $ LDA, XX, INCX ) + ELSE IF( PACKED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9995 )NC, SNAME, + $ UPLO, TRANS, DIAG, N, INCX + IF( REWI ) + $ REWIND NTRA + CALL DTPMV( UPLO, TRANS, DIAG, N, AA, XX, + $ INCX ) + END IF + ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN + IF( FULL )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9993 )NC, SNAME, + $ UPLO, TRANS, DIAG, N, LDA, INCX + IF( REWI ) + $ REWIND NTRA + CALL DTRSV( UPLO, TRANS, DIAG, N, AA, LDA, + $ XX, INCX ) + ELSE IF( BANDED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, + $ UPLO, TRANS, DIAG, N, K, LDA, INCX + IF( REWI ) + $ REWIND NTRA + CALL DTBSV( UPLO, TRANS, DIAG, N, K, AA, + $ LDA, XX, INCX ) + ELSE IF( PACKED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9995 )NC, SNAME, + $ UPLO, TRANS, DIAG, N, INCX + IF( REWI ) + $ REWIND NTRA + CALL DTPSV( UPLO, TRANS, DIAG, N, AA, XX, + $ INCX ) + END IF + END IF +* +* Check if error-exit was taken incorrectly. +* + IF( .NOT.OK )THEN + WRITE( NOUT, FMT = 9992 ) + FATAL = .TRUE. + GO TO 120 + END IF +* +* See what data changed inside subroutines. +* + ISAME( 1 ) = UPLO.EQ.UPLOS + ISAME( 2 ) = TRANS.EQ.TRANSS + ISAME( 3 ) = DIAG.EQ.DIAGS + ISAME( 4 ) = NS.EQ.N + IF( FULL )THEN + ISAME( 5 ) = LDE( AS, AA, LAA ) + ISAME( 6 ) = LDAS.EQ.LDA + IF( NULL )THEN + ISAME( 7 ) = LDE( XS, XX, LX ) + ELSE + ISAME( 7 ) = LDERES( 'GE', ' ', 1, N, XS, + $ XX, ABS( INCX ) ) + END IF + ISAME( 8 ) = INCXS.EQ.INCX + ELSE IF( BANDED )THEN + ISAME( 5 ) = KS.EQ.K + ISAME( 6 ) = LDE( AS, AA, LAA ) + ISAME( 7 ) = LDAS.EQ.LDA + IF( NULL )THEN + ISAME( 8 ) = LDE( XS, XX, LX ) + ELSE + ISAME( 8 ) = LDERES( 'GE', ' ', 1, N, XS, + $ XX, ABS( INCX ) ) + END IF + ISAME( 9 ) = INCXS.EQ.INCX + ELSE IF( PACKED )THEN + ISAME( 5 ) = LDE( AS, AA, LAA ) + IF( NULL )THEN + ISAME( 6 ) = LDE( XS, XX, LX ) + ELSE + ISAME( 6 ) = LDERES( 'GE', ' ', 1, N, XS, + $ XX, ABS( INCX ) ) + END IF + ISAME( 7 ) = INCXS.EQ.INCX + END IF +* +* If data was incorrectly changed, report and +* return. +* + SAME = .TRUE. + DO 40 I = 1, NARGS + SAME = SAME.AND.ISAME( I ) + IF( .NOT.ISAME( I ) ) + $ WRITE( NOUT, FMT = 9998 )I + 40 CONTINUE + IF( .NOT.SAME )THEN + FATAL = .TRUE. + GO TO 120 + END IF +* + IF( .NOT.NULL )THEN + IF( SNAME( 4: 5 ).EQ.'MV' )THEN +* +* Check the result. +* + CALL DMVCH( TRANS, N, N, ONE, A, NMAX, X, + $ INCX, ZERO, Z, INCX, XT, G, + $ XX, EPS, ERR, FATAL, NOUT, + $ .TRUE. ) + ELSE IF( SNAME( 4: 5 ).EQ.'SV' )THEN +* +* Compute approximation to original vector. +* + DO 50 I = 1, N + Z( I ) = XX( 1 + ( I - 1 )* + $ ABS( INCX ) ) + XX( 1 + ( I - 1 )*ABS( INCX ) ) + $ = X( I ) + 50 CONTINUE + CALL DMVCH( TRANS, N, N, ONE, A, NMAX, Z, + $ INCX, ZERO, X, INCX, XT, G, + $ XX, EPS, ERR, FATAL, NOUT, + $ .FALSE. ) + END IF + ERRMAX = MAX( ERRMAX, ERR ) +* If got really bad answer, report and return. + IF( FATAL ) + $ GO TO 120 + ELSE +* Avoid repeating tests with N.le.0. + GO TO 110 + END IF +* + 60 CONTINUE +* + 70 CONTINUE +* + 80 CONTINUE +* + 90 CONTINUE +* + 100 CONTINUE +* + 110 CONTINUE +* +* Report result. +* + IF( ERRMAX.LT.THRESH )THEN + WRITE( NOUT, FMT = 9999 )SNAME, NC + ELSE + WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX + END IF + GO TO 130 +* + 120 CONTINUE + WRITE( NOUT, FMT = 9996 )SNAME + IF( FULL )THEN + WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, TRANS, DIAG, N, LDA, + $ INCX + ELSE IF( BANDED )THEN + WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, TRANS, DIAG, N, K, + $ LDA, INCX + ELSE IF( PACKED )THEN + WRITE( NOUT, FMT = 9995 )NC, SNAME, UPLO, TRANS, DIAG, N, INCX + END IF +* + 130 CONTINUE + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', + $ 'S)' ) + 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', + $ 'ANGED INCORRECTLY *******' ) + 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', + $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, + $ ' - SUSPECT *******' ) + 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) + 9995 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', AP, ', + $ 'X,', I2, ') .' ) + 9994 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), 2( I3, ',' ), + $ ' A,', I3, ', X,', I2, ') .' ) + 9993 FORMAT( 1X, I6, ': ', A6, '(', 3( '''', A1, ''',' ), I3, ', A,', + $ I3, ', X,', I2, ') .' ) + 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', + $ '******' ) +* +* End of DCHK3. +* + END + SUBROUTINE DCHK4( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, + $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, + $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, + $ Z ) +* +* Tests DGER. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION EPS, THRESH + INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA + LOGICAL FATAL, REWI, TRACE + CHARACTER*6 SNAME +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), + $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), + $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), + $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), + $ YY( NMAX*INCMAX ), Z( NMAX ) + INTEGER IDIM( NIDIM ), INC( NINC ) +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX, TRANSL + INTEGER I, IA, IM, IN, INCX, INCXS, INCY, INCYS, IX, + $ IY, J, LAA, LDA, LDAS, LX, LY, M, MS, N, NARGS, + $ NC, ND, NS + LOGICAL NULL, RESET, SAME +* .. Local Arrays .. + DOUBLE PRECISION W( 1 ) + LOGICAL ISAME( 13 ) +* .. External Functions .. + LOGICAL LDE, LDERES + EXTERNAL LDE, LDERES +* .. External Subroutines .. + EXTERNAL DGER, DMAKE, DMVCH +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Executable Statements .. +* Define the number of arguments. + NARGS = 9 +* + NC = 0 + RESET = .TRUE. + ERRMAX = ZERO +* + DO 120 IN = 1, NIDIM + N = IDIM( IN ) + ND = N/2 + 1 +* + DO 110 IM = 1, 2 + IF( IM.EQ.1 ) + $ M = MAX( N - ND, 0 ) + IF( IM.EQ.2 ) + $ M = MIN( N + ND, NMAX ) +* +* Set LDA to 1 more than minimum value if room. + LDA = M + IF( LDA.LT.NMAX ) + $ LDA = LDA + 1 +* Skip tests if not enough room. + IF( LDA.GT.NMAX ) + $ GO TO 110 + LAA = LDA*N + NULL = N.LE.0.OR.M.LE.0 +* + DO 100 IX = 1, NINC + INCX = INC( IX ) + LX = ABS( INCX )*M +* +* Generate the vector X. +* + TRANSL = HALF + CALL DMAKE( 'GE', ' ', ' ', 1, M, X, 1, XX, ABS( INCX ), + $ 0, M - 1, RESET, TRANSL ) + IF( M.GT.1 )THEN + X( M/2 ) = ZERO + XX( 1 + ABS( INCX )*( M/2 - 1 ) ) = ZERO + END IF +* + DO 90 IY = 1, NINC + INCY = INC( IY ) + LY = ABS( INCY )*N +* +* Generate the vector Y. +* + TRANSL = ZERO + CALL DMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, + $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) + IF( N.GT.1 )THEN + Y( N/2 ) = ZERO + YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO + END IF +* + DO 80 IA = 1, NALF + ALPHA = ALF( IA ) +* +* Generate the matrix A. +* + TRANSL = ZERO + CALL DMAKE( SNAME( 2: 3 ), ' ', ' ', M, N, A, NMAX, + $ AA, LDA, M - 1, N - 1, RESET, TRANSL ) +* + NC = NC + 1 +* +* Save every datum before calling the subroutine. +* + MS = M + NS = N + ALS = ALPHA + DO 10 I = 1, LAA + AS( I ) = AA( I ) + 10 CONTINUE + LDAS = LDA + DO 20 I = 1, LX + XS( I ) = XX( I ) + 20 CONTINUE + INCXS = INCX + DO 30 I = 1, LY + YS( I ) = YY( I ) + 30 CONTINUE + INCYS = INCY +* +* Call the subroutine. +* + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, M, N, + $ ALPHA, INCX, INCY, LDA + IF( REWI ) + $ REWIND NTRA + CALL DGER( M, N, ALPHA, XX, INCX, YY, INCY, AA, + $ LDA ) +* +* Check if error-exit was taken incorrectly. +* + IF( .NOT.OK )THEN + WRITE( NOUT, FMT = 9993 ) + FATAL = .TRUE. + GO TO 140 + END IF +* +* See what data changed inside subroutine. +* + ISAME( 1 ) = MS.EQ.M + ISAME( 2 ) = NS.EQ.N + ISAME( 3 ) = ALS.EQ.ALPHA + ISAME( 4 ) = LDE( XS, XX, LX ) + ISAME( 5 ) = INCXS.EQ.INCX + ISAME( 6 ) = LDE( YS, YY, LY ) + ISAME( 7 ) = INCYS.EQ.INCY + IF( NULL )THEN + ISAME( 8 ) = LDE( AS, AA, LAA ) + ELSE + ISAME( 8 ) = LDERES( 'GE', ' ', M, N, AS, AA, + $ LDA ) + END IF + ISAME( 9 ) = LDAS.EQ.LDA +* +* If data was incorrectly changed, report and return. +* + SAME = .TRUE. + DO 40 I = 1, NARGS + SAME = SAME.AND.ISAME( I ) + IF( .NOT.ISAME( I ) ) + $ WRITE( NOUT, FMT = 9998 )I + 40 CONTINUE + IF( .NOT.SAME )THEN + FATAL = .TRUE. + GO TO 140 + END IF +* + IF( .NOT.NULL )THEN +* +* Check the result column by column. +* + IF( INCX.GT.0 )THEN + DO 50 I = 1, M + Z( I ) = X( I ) + 50 CONTINUE + ELSE + DO 60 I = 1, M + Z( I ) = X( M - I + 1 ) + 60 CONTINUE + END IF + DO 70 J = 1, N + IF( INCY.GT.0 )THEN + W( 1 ) = Y( J ) + ELSE + W( 1 ) = Y( N - J + 1 ) + END IF + CALL DMVCH( 'N', M, 1, ALPHA, Z, NMAX, W, 1, + $ ONE, A( 1, J ), 1, YT, G, + $ AA( 1 + ( J - 1 )*LDA ), EPS, + $ ERR, FATAL, NOUT, .TRUE. ) + ERRMAX = MAX( ERRMAX, ERR ) +* If got really bad answer, report and return. + IF( FATAL ) + $ GO TO 130 + 70 CONTINUE + ELSE +* Avoid repeating tests with M.le.0 or N.le.0. + GO TO 110 + END IF +* + 80 CONTINUE +* + 90 CONTINUE +* + 100 CONTINUE +* + 110 CONTINUE +* + 120 CONTINUE +* +* Report result. +* + IF( ERRMAX.LT.THRESH )THEN + WRITE( NOUT, FMT = 9999 )SNAME, NC + ELSE + WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX + END IF + GO TO 150 +* + 130 CONTINUE + WRITE( NOUT, FMT = 9995 )J +* + 140 CONTINUE + WRITE( NOUT, FMT = 9996 )SNAME + WRITE( NOUT, FMT = 9994 )NC, SNAME, M, N, ALPHA, INCX, INCY, LDA +* + 150 CONTINUE + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', + $ 'S)' ) + 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', + $ 'ANGED INCORRECTLY *******' ) + 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', + $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, + $ ' - SUSPECT *******' ) + 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) + 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) + 9994 FORMAT( 1X, I6, ': ', A6, '(', 2( I3, ',' ), F4.1, ', X,', I2, + $ ', Y,', I2, ', A,', I3, ') .' ) + 9993 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', + $ '******' ) +* +* End of DCHK4. +* + END + SUBROUTINE DCHK5( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, + $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, + $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, + $ Z ) +* +* Tests DSYR and DSPR. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION EPS, THRESH + INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA + LOGICAL FATAL, REWI, TRACE + CHARACTER*6 SNAME +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), + $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), + $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), + $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), + $ YY( NMAX*INCMAX ), Z( NMAX ) + INTEGER IDIM( NIDIM ), INC( NINC ) +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX, TRANSL + INTEGER I, IA, IC, IN, INCX, INCXS, IX, J, JA, JJ, LAA, + $ LDA, LDAS, LJ, LX, N, NARGS, NC, NS + LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER + CHARACTER*1 UPLO, UPLOS + CHARACTER*2 ICH +* .. Local Arrays .. + DOUBLE PRECISION W( 1 ) + LOGICAL ISAME( 13 ) +* .. External Functions .. + LOGICAL LDE, LDERES + EXTERNAL LDE, LDERES +* .. External Subroutines .. + EXTERNAL DMAKE, DMVCH, DSPR, DSYR +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Data statements .. + DATA ICH/'UL'/ +* .. Executable Statements .. + FULL = SNAME( 3: 3 ).EQ.'Y' + PACKED = SNAME( 3: 3 ).EQ.'P' +* Define the number of arguments. + IF( FULL )THEN + NARGS = 7 + ELSE IF( PACKED )THEN + NARGS = 6 + END IF +* + NC = 0 + RESET = .TRUE. + ERRMAX = ZERO +* + DO 100 IN = 1, NIDIM + N = IDIM( IN ) +* Set LDA to 1 more than minimum value if room. + LDA = N + IF( LDA.LT.NMAX ) + $ LDA = LDA + 1 +* Skip tests if not enough room. + IF( LDA.GT.NMAX ) + $ GO TO 100 + IF( PACKED )THEN + LAA = ( N*( N + 1 ) )/2 + ELSE + LAA = LDA*N + END IF +* + DO 90 IC = 1, 2 + UPLO = ICH( IC: IC ) + UPPER = UPLO.EQ.'U' +* + DO 80 IX = 1, NINC + INCX = INC( IX ) + LX = ABS( INCX )*N +* +* Generate the vector X. +* + TRANSL = HALF + CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), + $ 0, N - 1, RESET, TRANSL ) + IF( N.GT.1 )THEN + X( N/2 ) = ZERO + XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO + END IF +* + DO 70 IA = 1, NALF + ALPHA = ALF( IA ) + NULL = N.LE.0.OR.ALPHA.EQ.ZERO +* +* Generate the matrix A. +* + TRANSL = ZERO + CALL DMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, NMAX, + $ AA, LDA, N - 1, N - 1, RESET, TRANSL ) +* + NC = NC + 1 +* +* Save every datum before calling the subroutine. +* + UPLOS = UPLO + NS = N + ALS = ALPHA + DO 10 I = 1, LAA + AS( I ) = AA( I ) + 10 CONTINUE + LDAS = LDA + DO 20 I = 1, LX + XS( I ) = XX( I ) + 20 CONTINUE + INCXS = INCX +* +* Call the subroutine. +* + IF( FULL )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, + $ ALPHA, INCX, LDA + IF( REWI ) + $ REWIND NTRA + CALL DSYR( UPLO, N, ALPHA, XX, INCX, AA, LDA ) + ELSE IF( PACKED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, + $ ALPHA, INCX + IF( REWI ) + $ REWIND NTRA + CALL DSPR( UPLO, N, ALPHA, XX, INCX, AA ) + END IF +* +* Check if error-exit was taken incorrectly. +* + IF( .NOT.OK )THEN + WRITE( NOUT, FMT = 9992 ) + FATAL = .TRUE. + GO TO 120 + END IF +* +* See what data changed inside subroutines. +* + ISAME( 1 ) = UPLO.EQ.UPLOS + ISAME( 2 ) = NS.EQ.N + ISAME( 3 ) = ALS.EQ.ALPHA + ISAME( 4 ) = LDE( XS, XX, LX ) + ISAME( 5 ) = INCXS.EQ.INCX + IF( NULL )THEN + ISAME( 6 ) = LDE( AS, AA, LAA ) + ELSE + ISAME( 6 ) = LDERES( SNAME( 2: 3 ), UPLO, N, N, AS, + $ AA, LDA ) + END IF + IF( .NOT.PACKED )THEN + ISAME( 7 ) = LDAS.EQ.LDA + END IF +* +* If data was incorrectly changed, report and return. +* + SAME = .TRUE. + DO 30 I = 1, NARGS + SAME = SAME.AND.ISAME( I ) + IF( .NOT.ISAME( I ) ) + $ WRITE( NOUT, FMT = 9998 )I + 30 CONTINUE + IF( .NOT.SAME )THEN + FATAL = .TRUE. + GO TO 120 + END IF +* + IF( .NOT.NULL )THEN +* +* Check the result column by column. +* + IF( INCX.GT.0 )THEN + DO 40 I = 1, N + Z( I ) = X( I ) + 40 CONTINUE + ELSE + DO 50 I = 1, N + Z( I ) = X( N - I + 1 ) + 50 CONTINUE + END IF + JA = 1 + DO 60 J = 1, N + W( 1 ) = Z( J ) + IF( UPPER )THEN + JJ = 1 + LJ = J + ELSE + JJ = J + LJ = N - J + 1 + END IF + CALL DMVCH( 'N', LJ, 1, ALPHA, Z( JJ ), LJ, W, + $ 1, ONE, A( JJ, J ), 1, YT, G, + $ AA( JA ), EPS, ERR, FATAL, NOUT, + $ .TRUE. ) + IF( FULL )THEN + IF( UPPER )THEN + JA = JA + LDA + ELSE + JA = JA + LDA + 1 + END IF + ELSE + JA = JA + LJ + END IF + ERRMAX = MAX( ERRMAX, ERR ) +* If got really bad answer, report and return. + IF( FATAL ) + $ GO TO 110 + 60 CONTINUE + ELSE +* Avoid repeating tests if N.le.0. + IF( N.LE.0 ) + $ GO TO 100 + END IF +* + 70 CONTINUE +* + 80 CONTINUE +* + 90 CONTINUE +* + 100 CONTINUE +* +* Report result. +* + IF( ERRMAX.LT.THRESH )THEN + WRITE( NOUT, FMT = 9999 )SNAME, NC + ELSE + WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX + END IF + GO TO 130 +* + 110 CONTINUE + WRITE( NOUT, FMT = 9995 )J +* + 120 CONTINUE + WRITE( NOUT, FMT = 9996 )SNAME + IF( FULL )THEN + WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, LDA + ELSE IF( PACKED )THEN + WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX + END IF +* + 130 CONTINUE + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', + $ 'S)' ) + 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', + $ 'ANGED INCORRECTLY *******' ) + 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', + $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, + $ ' - SUSPECT *******' ) + 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) + 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) + 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', + $ I2, ', AP) .' ) + 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', + $ I2, ', A,', I3, ') .' ) + 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', + $ '******' ) +* +* End of DCHK5. +* + END + SUBROUTINE DCHK6( SNAME, EPS, THRESH, NOUT, NTRA, TRACE, REWI, + $ FATAL, NIDIM, IDIM, NALF, ALF, NINC, INC, NMAX, + $ INCMAX, A, AA, AS, X, XX, XS, Y, YY, YS, YT, G, + $ Z ) +* +* Tests DSYR2 and DSPR2. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION EPS, THRESH + INTEGER INCMAX, NALF, NIDIM, NINC, NMAX, NOUT, NTRA + LOGICAL FATAL, REWI, TRACE + CHARACTER*6 SNAME +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, NMAX ), AA( NMAX*NMAX ), ALF( NALF ), + $ AS( NMAX*NMAX ), G( NMAX ), X( NMAX ), + $ XS( NMAX*INCMAX ), XX( NMAX*INCMAX ), + $ Y( NMAX ), YS( NMAX*INCMAX ), YT( NMAX ), + $ YY( NMAX*INCMAX ), Z( NMAX, 2 ) + INTEGER IDIM( NIDIM ), INC( NINC ) +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, ALS, ERR, ERRMAX, TRANSL + INTEGER I, IA, IC, IN, INCX, INCXS, INCY, INCYS, IX, + $ IY, J, JA, JJ, LAA, LDA, LDAS, LJ, LX, LY, N, + $ NARGS, NC, NS + LOGICAL FULL, NULL, PACKED, RESET, SAME, UPPER + CHARACTER*1 UPLO, UPLOS + CHARACTER*2 ICH +* .. Local Arrays .. + DOUBLE PRECISION W( 2 ) + LOGICAL ISAME( 13 ) +* .. External Functions .. + LOGICAL LDE, LDERES + EXTERNAL LDE, LDERES +* .. External Subroutines .. + EXTERNAL DMAKE, DMVCH, DSPR2, DSYR2 +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Data statements .. + DATA ICH/'UL'/ +* .. Executable Statements .. + FULL = SNAME( 3: 3 ).EQ.'Y' + PACKED = SNAME( 3: 3 ).EQ.'P' +* Define the number of arguments. + IF( FULL )THEN + NARGS = 9 + ELSE IF( PACKED )THEN + NARGS = 8 + END IF +* + NC = 0 + RESET = .TRUE. + ERRMAX = ZERO +* + DO 140 IN = 1, NIDIM + N = IDIM( IN ) +* Set LDA to 1 more than minimum value if room. + LDA = N + IF( LDA.LT.NMAX ) + $ LDA = LDA + 1 +* Skip tests if not enough room. + IF( LDA.GT.NMAX ) + $ GO TO 140 + IF( PACKED )THEN + LAA = ( N*( N + 1 ) )/2 + ELSE + LAA = LDA*N + END IF +* + DO 130 IC = 1, 2 + UPLO = ICH( IC: IC ) + UPPER = UPLO.EQ.'U' +* + DO 120 IX = 1, NINC + INCX = INC( IX ) + LX = ABS( INCX )*N +* +* Generate the vector X. +* + TRANSL = HALF + CALL DMAKE( 'GE', ' ', ' ', 1, N, X, 1, XX, ABS( INCX ), + $ 0, N - 1, RESET, TRANSL ) + IF( N.GT.1 )THEN + X( N/2 ) = ZERO + XX( 1 + ABS( INCX )*( N/2 - 1 ) ) = ZERO + END IF +* + DO 110 IY = 1, NINC + INCY = INC( IY ) + LY = ABS( INCY )*N +* +* Generate the vector Y. +* + TRANSL = ZERO + CALL DMAKE( 'GE', ' ', ' ', 1, N, Y, 1, YY, + $ ABS( INCY ), 0, N - 1, RESET, TRANSL ) + IF( N.GT.1 )THEN + Y( N/2 ) = ZERO + YY( 1 + ABS( INCY )*( N/2 - 1 ) ) = ZERO + END IF +* + DO 100 IA = 1, NALF + ALPHA = ALF( IA ) + NULL = N.LE.0.OR.ALPHA.EQ.ZERO +* +* Generate the matrix A. +* + TRANSL = ZERO + CALL DMAKE( SNAME( 2: 3 ), UPLO, ' ', N, N, A, + $ NMAX, AA, LDA, N - 1, N - 1, RESET, + $ TRANSL ) +* + NC = NC + 1 +* +* Save every datum before calling the subroutine. +* + UPLOS = UPLO + NS = N + ALS = ALPHA + DO 10 I = 1, LAA + AS( I ) = AA( I ) + 10 CONTINUE + LDAS = LDA + DO 20 I = 1, LX + XS( I ) = XX( I ) + 20 CONTINUE + INCXS = INCX + DO 30 I = 1, LY + YS( I ) = YY( I ) + 30 CONTINUE + INCYS = INCY +* +* Call the subroutine. +* + IF( FULL )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9993 )NC, SNAME, UPLO, N, + $ ALPHA, INCX, INCY, LDA + IF( REWI ) + $ REWIND NTRA + CALL DSYR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, + $ AA, LDA ) + ELSE IF( PACKED )THEN + IF( TRACE ) + $ WRITE( NTRA, FMT = 9994 )NC, SNAME, UPLO, N, + $ ALPHA, INCX, INCY + IF( REWI ) + $ REWIND NTRA + CALL DSPR2( UPLO, N, ALPHA, XX, INCX, YY, INCY, + $ AA ) + END IF +* +* Check if error-exit was taken incorrectly. +* + IF( .NOT.OK )THEN + WRITE( NOUT, FMT = 9992 ) + FATAL = .TRUE. + GO TO 160 + END IF +* +* See what data changed inside subroutines. +* + ISAME( 1 ) = UPLO.EQ.UPLOS + ISAME( 2 ) = NS.EQ.N + ISAME( 3 ) = ALS.EQ.ALPHA + ISAME( 4 ) = LDE( XS, XX, LX ) + ISAME( 5 ) = INCXS.EQ.INCX + ISAME( 6 ) = LDE( YS, YY, LY ) + ISAME( 7 ) = INCYS.EQ.INCY + IF( NULL )THEN + ISAME( 8 ) = LDE( AS, AA, LAA ) + ELSE + ISAME( 8 ) = LDERES( SNAME( 2: 3 ), UPLO, N, N, + $ AS, AA, LDA ) + END IF + IF( .NOT.PACKED )THEN + ISAME( 9 ) = LDAS.EQ.LDA + END IF +* +* If data was incorrectly changed, report and return. +* + SAME = .TRUE. + DO 40 I = 1, NARGS + SAME = SAME.AND.ISAME( I ) + IF( .NOT.ISAME( I ) ) + $ WRITE( NOUT, FMT = 9998 )I + 40 CONTINUE + IF( .NOT.SAME )THEN + FATAL = .TRUE. + GO TO 160 + END IF +* + IF( .NOT.NULL )THEN +* +* Check the result column by column. +* + IF( INCX.GT.0 )THEN + DO 50 I = 1, N + Z( I, 1 ) = X( I ) + 50 CONTINUE + ELSE + DO 60 I = 1, N + Z( I, 1 ) = X( N - I + 1 ) + 60 CONTINUE + END IF + IF( INCY.GT.0 )THEN + DO 70 I = 1, N + Z( I, 2 ) = Y( I ) + 70 CONTINUE + ELSE + DO 80 I = 1, N + Z( I, 2 ) = Y( N - I + 1 ) + 80 CONTINUE + END IF + JA = 1 + DO 90 J = 1, N + W( 1 ) = Z( J, 2 ) + W( 2 ) = Z( J, 1 ) + IF( UPPER )THEN + JJ = 1 + LJ = J + ELSE + JJ = J + LJ = N - J + 1 + END IF + CALL DMVCH( 'N', LJ, 2, ALPHA, Z( JJ, 1 ), + $ NMAX, W, 1, ONE, A( JJ, J ), 1, + $ YT, G, AA( JA ), EPS, ERR, FATAL, + $ NOUT, .TRUE. ) + IF( FULL )THEN + IF( UPPER )THEN + JA = JA + LDA + ELSE + JA = JA + LDA + 1 + END IF + ELSE + JA = JA + LJ + END IF + ERRMAX = MAX( ERRMAX, ERR ) +* If got really bad answer, report and return. + IF( FATAL ) + $ GO TO 150 + 90 CONTINUE + ELSE +* Avoid repeating tests with N.le.0. + IF( N.LE.0 ) + $ GO TO 140 + END IF +* + 100 CONTINUE +* + 110 CONTINUE +* + 120 CONTINUE +* + 130 CONTINUE +* + 140 CONTINUE +* +* Report result. +* + IF( ERRMAX.LT.THRESH )THEN + WRITE( NOUT, FMT = 9999 )SNAME, NC + ELSE + WRITE( NOUT, FMT = 9997 )SNAME, NC, ERRMAX + END IF + GO TO 170 +* + 150 CONTINUE + WRITE( NOUT, FMT = 9995 )J +* + 160 CONTINUE + WRITE( NOUT, FMT = 9996 )SNAME + IF( FULL )THEN + WRITE( NOUT, FMT = 9993 )NC, SNAME, UPLO, N, ALPHA, INCX, + $ INCY, LDA + ELSE IF( PACKED )THEN + WRITE( NOUT, FMT = 9994 )NC, SNAME, UPLO, N, ALPHA, INCX, INCY + END IF +* + 170 CONTINUE + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE COMPUTATIONAL TESTS (', I6, ' CALL', + $ 'S)' ) + 9998 FORMAT( ' ******* FATAL ERROR - PARAMETER NUMBER ', I2, ' WAS CH', + $ 'ANGED INCORRECTLY *******' ) + 9997 FORMAT( ' ', A6, ' COMPLETED THE COMPUTATIONAL TESTS (', I6, ' C', + $ 'ALLS)', /' ******* BUT WITH MAXIMUM TEST RATIO', F8.2, + $ ' - SUSPECT *******' ) + 9996 FORMAT( ' ******* ', A6, ' FAILED ON CALL NUMBER:' ) + 9995 FORMAT( ' THESE ARE THE RESULTS FOR COLUMN ', I3 ) + 9994 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', + $ I2, ', Y,', I2, ', AP) .' ) + 9993 FORMAT( 1X, I6, ': ', A6, '(''', A1, ''',', I3, ',', F4.1, ', X,', + $ I2, ', Y,', I2, ', A,', I3, ') .' ) + 9992 FORMAT( ' ******* FATAL ERROR - ERROR-EXIT TAKEN ON VALID CALL *', + $ '******' ) +* +* End of DCHK6. +* + END + SUBROUTINE DCHKE( ISNUM, SRNAMT, NOUT ) +* +* Tests the error exits from the Level 2 Blas. +* Requires a special version of the error-handling routine XERBLA. +* ALPHA, BETA, A, X and Y should not need to be defined. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Scalar Arguments .. + INTEGER ISNUM, NOUT + CHARACTER*6 SRNAMT +* .. Scalars in Common .. + INTEGER INFOT, NOUTC + LOGICAL LERR, OK +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, BETA +* .. Local Arrays .. + DOUBLE PRECISION A( 1, 1 ), X( 1 ), Y( 1 ) +* .. External Subroutines .. + EXTERNAL CHKXER, DGBMV, DGEMV, DGER, DSBMV, DSPMV, DSPR, + $ DSPR2, DSYMV, DSYR, DSYR2, DTBMV, DTBSV, DTPMV, + $ DTPSV, DTRMV, DTRSV +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUTC, OK, LERR +* .. Executable Statements .. +* OK is set to .FALSE. by the special version of XERBLA or by CHKXER +* if anything is wrong. + OK = .TRUE. +* LERR is set to .TRUE. by the special version of XERBLA each time +* it is called, and is then tested and re-set by CHKXER. + LERR = .FALSE. + GO TO ( 10, 20, 30, 40, 50, 60, 70, 80, + $ 90, 100, 110, 120, 130, 140, 150, + $ 160 )ISNUM + 10 INFOT = 1 + CALL DGEMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DGEMV( 'N', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DGEMV( 'N', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 6 + CALL DGEMV( 'N', 2, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 8 + CALL DGEMV( 'N', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 11 + CALL DGEMV( 'N', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 20 INFOT = 1 + CALL DGBMV( '/', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DGBMV( 'N', -1, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DGBMV( 'N', 0, -1, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DGBMV( 'N', 0, 0, -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DGBMV( 'N', 2, 0, 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 8 + CALL DGBMV( 'N', 0, 0, 1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 10 + CALL DGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 13 + CALL DGBMV( 'N', 0, 0, 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 30 INFOT = 1 + CALL DSYMV( '/', 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSYMV( 'U', -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DSYMV( 'U', 2, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DSYMV( 'U', 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 10 + CALL DSYMV( 'U', 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 40 INFOT = 1 + CALL DSBMV( '/', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSBMV( 'U', -1, 0, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DSBMV( 'U', 0, -1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 6 + CALL DSBMV( 'U', 0, 1, ALPHA, A, 1, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 8 + CALL DSBMV( 'U', 0, 0, ALPHA, A, 1, X, 0, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 11 + CALL DSBMV( 'U', 0, 0, ALPHA, A, 1, X, 1, BETA, Y, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 50 INFOT = 1 + CALL DSPMV( '/', 0, ALPHA, A, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSPMV( 'U', -1, ALPHA, A, X, 1, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 6 + CALL DSPMV( 'U', 0, ALPHA, A, X, 0, BETA, Y, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 9 + CALL DSPMV( 'U', 0, ALPHA, A, X, 1, BETA, Y, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 60 INFOT = 1 + CALL DTRMV( '/', 'N', 'N', 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DTRMV( 'U', '/', 'N', 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DTRMV( 'U', 'N', '/', 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DTRMV( 'U', 'N', 'N', -1, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 6 + CALL DTRMV( 'U', 'N', 'N', 2, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 8 + CALL DTRMV( 'U', 'N', 'N', 0, A, 1, X, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 70 INFOT = 1 + CALL DTBMV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DTBMV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DTBMV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DTBMV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DTBMV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DTBMV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 9 + CALL DTBMV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 80 INFOT = 1 + CALL DTPMV( '/', 'N', 'N', 0, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DTPMV( 'U', '/', 'N', 0, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DTPMV( 'U', 'N', '/', 0, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DTPMV( 'U', 'N', 'N', -1, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DTPMV( 'U', 'N', 'N', 0, A, X, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 90 INFOT = 1 + CALL DTRSV( '/', 'N', 'N', 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DTRSV( 'U', '/', 'N', 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DTRSV( 'U', 'N', '/', 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DTRSV( 'U', 'N', 'N', -1, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 6 + CALL DTRSV( 'U', 'N', 'N', 2, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 8 + CALL DTRSV( 'U', 'N', 'N', 0, A, 1, X, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 100 INFOT = 1 + CALL DTBSV( '/', 'N', 'N', 0, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DTBSV( 'U', '/', 'N', 0, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DTBSV( 'U', 'N', '/', 0, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DTBSV( 'U', 'N', 'N', -1, 0, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DTBSV( 'U', 'N', 'N', 0, -1, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DTBSV( 'U', 'N', 'N', 0, 1, A, 1, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 9 + CALL DTBSV( 'U', 'N', 'N', 0, 0, A, 1, X, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 110 INFOT = 1 + CALL DTPSV( '/', 'N', 'N', 0, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DTPSV( 'U', '/', 'N', 0, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 3 + CALL DTPSV( 'U', 'N', '/', 0, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 4 + CALL DTPSV( 'U', 'N', 'N', -1, A, X, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DTPSV( 'U', 'N', 'N', 0, A, X, 0 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 120 INFOT = 1 + CALL DGER( -1, 0, ALPHA, X, 1, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DGER( 0, -1, ALPHA, X, 1, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DGER( 0, 0, ALPHA, X, 0, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DGER( 0, 0, ALPHA, X, 1, Y, 0, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 9 + CALL DGER( 2, 0, ALPHA, X, 1, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 130 INFOT = 1 + CALL DSYR( '/', 0, ALPHA, X, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSYR( 'U', -1, ALPHA, X, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DSYR( 'U', 0, ALPHA, X, 0, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DSYR( 'U', 2, ALPHA, X, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 140 INFOT = 1 + CALL DSPR( '/', 0, ALPHA, X, 1, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSPR( 'U', -1, ALPHA, X, 1, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DSPR( 'U', 0, ALPHA, X, 0, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 150 INFOT = 1 + CALL DSYR2( '/', 0, ALPHA, X, 1, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSYR2( 'U', -1, ALPHA, X, 1, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DSYR2( 'U', 0, ALPHA, X, 0, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DSYR2( 'U', 0, ALPHA, X, 1, Y, 0, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 9 + CALL DSYR2( 'U', 2, ALPHA, X, 1, Y, 1, A, 1 ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + GO TO 170 + 160 INFOT = 1 + CALL DSPR2( '/', 0, ALPHA, X, 1, Y, 1, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 2 + CALL DSPR2( 'U', -1, ALPHA, X, 1, Y, 1, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 5 + CALL DSPR2( 'U', 0, ALPHA, X, 0, Y, 1, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) + INFOT = 7 + CALL DSPR2( 'U', 0, ALPHA, X, 1, Y, 0, A ) + CALL CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) +* + 170 IF( OK )THEN + WRITE( NOUT, FMT = 9999 )SRNAMT + ELSE + WRITE( NOUT, FMT = 9998 )SRNAMT + END IF + RETURN +* + 9999 FORMAT( ' ', A6, ' PASSED THE TESTS OF ERROR-EXITS' ) + 9998 FORMAT( ' ******* ', A6, ' FAILED THE TESTS OF ERROR-EXITS *****', + $ '**' ) +* +* End of DCHKE. +* + END + SUBROUTINE DMAKE( TYPE, UPLO, DIAG, M, N, A, NMAX, AA, LDA, KL, + $ KU, RESET, TRANSL ) +* +* Generates values for an M by N matrix A within the bandwidth +* defined by KL and KU. +* Stores the values in the array AA in the data structure required +* by the routine, with unwanted elements set to rogue value. +* +* TYPE is 'GE', 'GB', 'SY', 'SB', 'SP', 'TR', 'TB' OR 'TP'. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) + DOUBLE PRECISION ROGUE + PARAMETER ( ROGUE = -1.0D10 ) +* .. Scalar Arguments .. + DOUBLE PRECISION TRANSL + INTEGER KL, KU, LDA, M, N, NMAX + LOGICAL RESET + CHARACTER*1 DIAG, UPLO + CHARACTER*2 TYPE +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, * ), AA( * ) +* .. Local Scalars .. + INTEGER I, I1, I2, I3, IBEG, IEND, IOFF, J, KK + LOGICAL GEN, LOWER, SYM, TRI, UNIT, UPPER +* .. External Functions .. + DOUBLE PRECISION DBEG + EXTERNAL DBEG +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. Executable Statements .. + GEN = TYPE( 1: 1 ).EQ.'G' + SYM = TYPE( 1: 1 ).EQ.'S' + TRI = TYPE( 1: 1 ).EQ.'T' + UPPER = ( SYM.OR.TRI ).AND.UPLO.EQ.'U' + LOWER = ( SYM.OR.TRI ).AND.UPLO.EQ.'L' + UNIT = TRI.AND.DIAG.EQ.'U' +* +* Generate data in array A. +* + DO 20 J = 1, N + DO 10 I = 1, M + IF( GEN.OR.( UPPER.AND.I.LE.J ).OR.( LOWER.AND.I.GE.J ) ) + $ THEN + IF( ( I.LE.J.AND.J - I.LE.KU ).OR. + $ ( I.GE.J.AND.I - J.LE.KL ) )THEN + A( I, J ) = DBEG( RESET ) + TRANSL + ELSE + A( I, J ) = ZERO + END IF + IF( I.NE.J )THEN + IF( SYM )THEN + A( J, I ) = A( I, J ) + ELSE IF( TRI )THEN + A( J, I ) = ZERO + END IF + END IF + END IF + 10 CONTINUE + IF( TRI ) + $ A( J, J ) = A( J, J ) + ONE + IF( UNIT ) + $ A( J, J ) = ONE + 20 CONTINUE +* +* Store elements in array AS in data structure required by routine. +* + IF( TYPE.EQ.'GE' )THEN + DO 50 J = 1, N + DO 30 I = 1, M + AA( I + ( J - 1 )*LDA ) = A( I, J ) + 30 CONTINUE + DO 40 I = M + 1, LDA + AA( I + ( J - 1 )*LDA ) = ROGUE + 40 CONTINUE + 50 CONTINUE + ELSE IF( TYPE.EQ.'GB' )THEN + DO 90 J = 1, N + DO 60 I1 = 1, KU + 1 - J + AA( I1 + ( J - 1 )*LDA ) = ROGUE + 60 CONTINUE + DO 70 I2 = I1, MIN( KL + KU + 1, KU + 1 + M - J ) + AA( I2 + ( J - 1 )*LDA ) = A( I2 + J - KU - 1, J ) + 70 CONTINUE + DO 80 I3 = I2, LDA + AA( I3 + ( J - 1 )*LDA ) = ROGUE + 80 CONTINUE + 90 CONTINUE + ELSE IF( TYPE.EQ.'SY'.OR.TYPE.EQ.'TR' )THEN + DO 130 J = 1, N + IF( UPPER )THEN + IBEG = 1 + IF( UNIT )THEN + IEND = J - 1 + ELSE + IEND = J + END IF + ELSE + IF( UNIT )THEN + IBEG = J + 1 + ELSE + IBEG = J + END IF + IEND = N + END IF + DO 100 I = 1, IBEG - 1 + AA( I + ( J - 1 )*LDA ) = ROGUE + 100 CONTINUE + DO 110 I = IBEG, IEND + AA( I + ( J - 1 )*LDA ) = A( I, J ) + 110 CONTINUE + DO 120 I = IEND + 1, LDA + AA( I + ( J - 1 )*LDA ) = ROGUE + 120 CONTINUE + 130 CONTINUE + ELSE IF( TYPE.EQ.'SB'.OR.TYPE.EQ.'TB' )THEN + DO 170 J = 1, N + IF( UPPER )THEN + KK = KL + 1 + IBEG = MAX( 1, KL + 2 - J ) + IF( UNIT )THEN + IEND = KL + ELSE + IEND = KL + 1 + END IF + ELSE + KK = 1 + IF( UNIT )THEN + IBEG = 2 + ELSE + IBEG = 1 + END IF + IEND = MIN( KL + 1, 1 + M - J ) + END IF + DO 140 I = 1, IBEG - 1 + AA( I + ( J - 1 )*LDA ) = ROGUE + 140 CONTINUE + DO 150 I = IBEG, IEND + AA( I + ( J - 1 )*LDA ) = A( I + J - KK, J ) + 150 CONTINUE + DO 160 I = IEND + 1, LDA + AA( I + ( J - 1 )*LDA ) = ROGUE + 160 CONTINUE + 170 CONTINUE + ELSE IF( TYPE.EQ.'SP'.OR.TYPE.EQ.'TP' )THEN + IOFF = 0 + DO 190 J = 1, N + IF( UPPER )THEN + IBEG = 1 + IEND = J + ELSE + IBEG = J + IEND = N + END IF + DO 180 I = IBEG, IEND + IOFF = IOFF + 1 + AA( IOFF ) = A( I, J ) + IF( I.EQ.J )THEN + IF( UNIT ) + $ AA( IOFF ) = ROGUE + END IF + 180 CONTINUE + 190 CONTINUE + END IF + RETURN +* +* End of DMAKE. +* + END + SUBROUTINE DMVCH( TRANS, M, N, ALPHA, A, NMAX, X, INCX, BETA, Y, + $ INCY, YT, G, YY, EPS, ERR, FATAL, NOUT, MV ) +* +* Checks the results of the computational tests. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA, BETA, EPS, ERR + INTEGER INCX, INCY, M, N, NMAX, NOUT + LOGICAL FATAL, MV + CHARACTER*1 TRANS +* .. Array Arguments .. + DOUBLE PRECISION A( NMAX, * ), G( * ), X( * ), Y( * ), YT( * ), + $ YY( * ) +* .. Local Scalars .. + DOUBLE PRECISION ERRI + INTEGER I, INCXL, INCYL, IY, J, JX, KX, KY, ML, NL + LOGICAL TRAN +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. Executable Statements .. + TRAN = TRANS.EQ.'T'.OR.TRANS.EQ.'C' + IF( TRAN )THEN + ML = N + NL = M + ELSE + ML = M + NL = N + END IF + IF( INCX.LT.0 )THEN + KX = NL + INCXL = -1 + ELSE + KX = 1 + INCXL = 1 + END IF + IF( INCY.LT.0 )THEN + KY = ML + INCYL = -1 + ELSE + KY = 1 + INCYL = 1 + END IF +* +* Compute expected result in YT using data in A, X and Y. +* Compute gauges in G. +* + IY = KY + DO 30 I = 1, ML + YT( IY ) = ZERO + G( IY ) = ZERO + JX = KX + IF( TRAN )THEN + DO 10 J = 1, NL + YT( IY ) = YT( IY ) + A( J, I )*X( JX ) + G( IY ) = G( IY ) + ABS( A( J, I )*X( JX ) ) + JX = JX + INCXL + 10 CONTINUE + ELSE + DO 20 J = 1, NL + YT( IY ) = YT( IY ) + A( I, J )*X( JX ) + G( IY ) = G( IY ) + ABS( A( I, J )*X( JX ) ) + JX = JX + INCXL + 20 CONTINUE + END IF + YT( IY ) = ALPHA*YT( IY ) + BETA*Y( IY ) + G( IY ) = ABS( ALPHA )*G( IY ) + ABS( BETA*Y( IY ) ) + IY = IY + INCYL + 30 CONTINUE +* +* Compute the error ratio for this result. +* + ERR = ZERO + DO 40 I = 1, ML + ERRI = ABS( YT( I ) - YY( 1 + ( I - 1 )*ABS( INCY ) ) )/EPS + IF( G( I ).NE.ZERO ) + $ ERRI = ERRI/G( I ) + ERR = MAX( ERR, ERRI ) + IF( ERR*SQRT( EPS ).GE.ONE ) + $ GO TO 50 + 40 CONTINUE +* If the loop completes, all results are at least half accurate. + GO TO 70 +* +* Report fatal error. +* + 50 FATAL = .TRUE. + WRITE( NOUT, FMT = 9999 ) + DO 60 I = 1, ML + IF( MV )THEN + WRITE( NOUT, FMT = 9998 )I, YT( I ), + $ YY( 1 + ( I - 1 )*ABS( INCY ) ) + ELSE + WRITE( NOUT, FMT = 9998 )I, + $ YY( 1 + ( I - 1 )*ABS( INCY ) ), YT( I ) + END IF + 60 CONTINUE +* + 70 CONTINUE + RETURN +* + 9999 FORMAT( ' ******* FATAL ERROR - COMPUTED RESULT IS LESS THAN HAL', + $ 'F ACCURATE *******', /' EXPECTED RESULT COMPU', + $ 'TED RESULT' ) + 9998 FORMAT( 1X, I7, 2G18.6 ) +* +* End of DMVCH. +* + END + LOGICAL FUNCTION LDE( RI, RJ, LR ) +* +* Tests if two arrays are identical. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Scalar Arguments .. + INTEGER LR +* .. Array Arguments .. + DOUBLE PRECISION RI( * ), RJ( * ) +* .. Local Scalars .. + INTEGER I +* .. Executable Statements .. + DO 10 I = 1, LR + IF( RI( I ).NE.RJ( I ) ) + $ GO TO 20 + 10 CONTINUE + LDE = .TRUE. + GO TO 30 + 20 CONTINUE + LDE = .FALSE. + 30 RETURN +* +* End of LDE. +* + END + LOGICAL FUNCTION LDERES( TYPE, UPLO, M, N, AA, AS, LDA ) +* +* Tests if selected elements in two arrays are equal. +* +* TYPE is 'GE', 'SY' or 'SP'. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Scalar Arguments .. + INTEGER LDA, M, N + CHARACTER*1 UPLO + CHARACTER*2 TYPE +* .. Array Arguments .. + DOUBLE PRECISION AA( LDA, * ), AS( LDA, * ) +* .. Local Scalars .. + INTEGER I, IBEG, IEND, J + LOGICAL UPPER +* .. Executable Statements .. + UPPER = UPLO.EQ.'U' + IF( TYPE.EQ.'GE' )THEN + DO 20 J = 1, N + DO 10 I = M + 1, LDA + IF( AA( I, J ).NE.AS( I, J ) ) + $ GO TO 70 + 10 CONTINUE + 20 CONTINUE + ELSE IF( TYPE.EQ.'SY' )THEN + DO 50 J = 1, N + IF( UPPER )THEN + IBEG = 1 + IEND = J + ELSE + IBEG = J + IEND = N + END IF + DO 30 I = 1, IBEG - 1 + IF( AA( I, J ).NE.AS( I, J ) ) + $ GO TO 70 + 30 CONTINUE + DO 40 I = IEND + 1, LDA + IF( AA( I, J ).NE.AS( I, J ) ) + $ GO TO 70 + 40 CONTINUE + 50 CONTINUE + END IF +* + LDERES = .TRUE. + GO TO 80 + 70 CONTINUE + LDERES = .FALSE. + 80 RETURN +* +* End of LDERES. +* + END + DOUBLE PRECISION FUNCTION DBEG( RESET ) +* +* Generates random numbers uniformly distributed between -0.5 and 0.5. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Scalar Arguments .. + LOGICAL RESET +* .. Local Scalars .. + INTEGER I, IC, MI +* .. Save statement .. + SAVE I, IC, MI +* .. Intrinsic Functions .. + INTRINSIC DBLE +* .. Executable Statements .. + IF( RESET )THEN +* Initialize local variables. + MI = 891 + I = 7 + IC = 0 + RESET = .FALSE. + END IF +* +* The sequence of values of I is bounded between 1 and 999. +* If initial I = 1,2,3,6,7 or 9, the period will be 50. +* If initial I = 4 or 8, the period will be 25. +* If initial I = 5, the period will be 10. +* IC is used to break up the period by skipping 1 value of I in 6. +* + IC = IC + 1 + 10 I = I*MI + I = I - 1000*( I/1000 ) + IF( IC.GE.5 )THEN + IC = 0 + GO TO 10 + END IF + DBEG = DBLE( I - 500 )/1001.0D0 + RETURN +* +* End of DBEG. +* + END + DOUBLE PRECISION FUNCTION DDIFF( X, Y ) +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y +* .. Executable Statements .. + DDIFF = X - Y + RETURN +* +* End of DDIFF. +* + END + SUBROUTINE CHKXER( SRNAMT, INFOT, NOUT, LERR, OK ) +* +* Tests whether XERBLA has detected an error when it should. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Scalar Arguments .. + INTEGER INFOT, NOUT + LOGICAL LERR, OK + CHARACTER*6 SRNAMT +* .. Executable Statements .. + IF( .NOT.LERR )THEN + WRITE( NOUT, FMT = 9999 )INFOT, SRNAMT + OK = .FALSE. + END IF + LERR = .FALSE. + RETURN +* + 9999 FORMAT( ' ***** ILLEGAL VALUE OF PARAMETER NUMBER ', I2, ' NOT D', + $ 'ETECTED BY ', A6, ' *****' ) +* +* End of CHKXER. +* + END + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* This is a special version of XERBLA to be used only as part of +* the test program for testing error exits from the Level 2 BLAS +* routines. +* +* XERBLA is an error handler for the Level 2 BLAS routines. +* +* It is called by the Level 2 BLAS routines if an input parameter is +* invalid. +* +* Auxiliary routine for test program for Level 2 Blas. +* +* -- Written on 10-August-1987. +* Richard Hanson, Sandia National Labs. +* Jeremy Du Croz, NAG Central Office. +* +* .. Scalar Arguments .. + INTEGER INFO + CHARACTER*6 SRNAME +* .. Scalars in Common .. + INTEGER INFOT, NOUT + LOGICAL LERR, OK + CHARACTER*6 SRNAMT +* .. Common blocks .. + COMMON /INFOC/INFOT, NOUT, OK, LERR + COMMON /SRNAMC/SRNAMT +* .. Executable Statements .. + LERR = .TRUE. + IF( INFO.NE.INFOT )THEN + IF( INFOT.NE.0 )THEN + WRITE( NOUT, FMT = 9999 )INFO, INFOT + ELSE + WRITE( NOUT, FMT = 9997 )INFO + END IF + OK = .FALSE. + END IF + IF( SRNAME.NE.SRNAMT )THEN + WRITE( NOUT, FMT = 9998 )SRNAME, SRNAMT + OK = .FALSE. + END IF + RETURN +* + 9999 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, ' INSTEAD', + $ ' OF ', I2, ' *******' ) + 9998 FORMAT( ' ******* XERBLA WAS CALLED WITH SRNAME = ', A6, ' INSTE', + $ 'AD OF ', A6, ' *******' ) + 9997 FORMAT( ' ******* XERBLA WAS CALLED WITH INFO = ', I6, + $ ' *******' ) +* +* End of XERBLA +* + END + diff --git a/tests/fr.cnes.analysis.tools.fortran77.rules.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.fortran77.rules.test/META-INF/MANIFEST.MF index 86c0dd80..fa8ce77a 100644 --- a/tests/fr.cnes.analysis.tools.fortran77.rules.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.fortran77.rules.test/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES F77 Rules Bundle-SymbolicName: fr.cnes.analysis.tools.fortran77.rules.test -Bundle-Version: 3.0.1.qualifier -Fragment-Host: fr.cnes.analysis.tools.fortran77.rules;bundle-version="3.0.1" +Bundle-Version: 3.1.0.qualifier +Fragment-Host: fr.cnes.analysis.tools.fortran77.rules;bundle-version="3.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.mockito;bundle-version="1.8.4", org.hamcrest;bundle-version="1.1.0", diff --git a/tests/fr.cnes.analysis.tools.fortran77.rules.test/pom.xml b/tests/fr.cnes.analysis.tools.fortran77.rules.test/pom.xml index 319abb18..5c3b6728 100644 --- a/tests/fr.cnes.analysis.tools.fortran77.rules.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.fortran77.rules.test/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran77.rules.test diff --git a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/META-INF/MANIFEST.MF index 068fd44c..3aae3fbe 100644 --- a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES F90 Metrics Bundle-SymbolicName: fr.cnes.analysis.tools.fortran90.metrics.test -Bundle-Version: 3.0.1.qualifier -Fragment-Host: fr.cnes.analysis.tools.fortran90.metrics;bundle-version="3.0.1" +Bundle-Version: 3.1.0.qualifier +Fragment-Host: fr.cnes.analysis.tools.fortran90.metrics;bundle-version="3.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: fr.cnes.analysis.tools.fortran90.metrics Require-Bundle: org.mockito;bundle-version="1.8.4", diff --git a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/pom.xml b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/pom.xml index 718e204f..63af12a3 100644 --- a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran90.metrics.test diff --git a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/AllTests.java b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/AllTests.java index 7801fc03..74395a27 100755 --- a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/AllTests.java +++ b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/AllTests.java @@ -6,6 +6,7 @@ import fr.cnes.analysis.tools.fortran90.metrics.ComplexitySimplified.TestF90METComplexitySimplified; import fr.cnes.analysis.tools.fortran90.metrics.LineOfCode.TestF90METLineOfCode; +import fr.cnes.analysis.tools.fortran90.metrics.LineOfComment.TestF90METLineOfComment; import fr.cnes.analysis.tools.fortran90.metrics.Nesting.TestF90METNesting; import fr.cnes.analysis.tools.fortran90.metrics.RatioComment.TestF90METRatioComment; @@ -13,6 +14,7 @@ @SuiteClasses({TestF90METNesting.class, TestF90METComplexitySimplified.class, TestF90METLineOfCode.class, + TestF90METLineOfComment.class, TestF90METRatioComment.class}) public class AllTests { diff --git a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/LineOfComment/TestF90METLineOfComment.java b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/LineOfComment/TestF90METLineOfComment.java new file mode 100644 index 00000000..9b0069e2 --- /dev/null +++ b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/LineOfComment/TestF90METLineOfComment.java @@ -0,0 +1,98 @@ +/************************************************************************************************/ +/** i-Code CNES is a static code analyzer. */ +/** This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/** http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ +package fr.cnes.analysis.tools.fortran90.metrics.LineOfComment; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.fortran90.metrics.F90METLineOfComment; +import fr.cnes.analysis.tools.fortran90.metrics.TestUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.core.runtime.FileLocator; +import org.junit.Test; + +/** + * This class aims to test Don.Declaration rule. There are 2 functions in this + * class. The first one verifies that an error in a file is detected whenever + * there is one, the other verifies that nothing is detected when there's no + * error. + */ +public class TestF90METLineOfComment { + + /** + * This test verifies that an error can be detected. + */ + @Test + public void testRunWithError() { + + try { + // Initializing rule and getting error file. + final AbstractChecker metric = new F90METLineOfComment(); + final String fileName = "type_var2d_pdf2d.f90"; + final File file = new File( + FileLocator.resolve(this.getClass().getResource(fileName)).getFile()); + + // Defining file in the rule instantiation. + metric.setContribution(TestUtils.getContribution("", "")); + metric.setInputFile(file); + + // File Value + final List checkResults = metric.run(); + CheckResult fileValue = null; + for (CheckResult check : checkResults) { + if (check.getLocation()==null || check.getLocation().isEmpty()) { + fileValue = check; + checkResults.remove(checkResults.indexOf(check)); + } + } + + if (fileValue == null) { + fail("Erreur : Aucun r�sultat sur le fichier trouv�."); + } else { + + + // Value 1 + assertTrue("Test except a file value of ["+145.0 +"] while metric computed ["+Math.round(fileValue.getValue())+"].", fileValue.getValue().equals((float)145.0)); + + final List functionValues = checkResults; + Map exceptedValues = new TreeMap<>(); + exceptedValues.put("function interpolate_var2d_pdf2d_dp",(float)22.0); + exceptedValues.put("function interpolate_var2d_pdf2d_sp",(float)22.0); + exceptedValues.put("function set_var2d_pdf2d_dp",(float)18.0); + exceptedValues.put("function set_var2d_pdf2d_sp",(float)18.0); + exceptedValues.put("interface interpolate_var2d_pdf2d",(float)0.0); + exceptedValues.put("interface sample_var2d_pdf2d",(float)0.0); + exceptedValues.put("interface set_var2d_pdf2d",(float)0.0); + exceptedValues.put("module type_var2d_pdf2d",(float)4.0); + exceptedValues.put("subroutine sample_var2d_pdf2d_dp",(float)17.0); + exceptedValues.put("subroutine sample_var2d_pdf2d_sp",(float)17.0); + + for(CheckResult metricValue : functionValues){ + assertTrue("Test do not excepts function : "+metricValue.getLocation()+".",exceptedValues.containsKey(metricValue.getLocation())); + assertTrue("Test excepts value of ["+Math.round(exceptedValues.get(metricValue.getLocation()))+"] while metric computed ["+Math.round(metricValue.getValue())+"] for the function "+metricValue.getLocation()+".",Math.round(metricValue.getValue()) == Math.round(exceptedValues.get(metricValue.getLocation()))); + } + assertTrue("Test excepts "+exceptedValues.size()+" functions computed for the file while the metric computed ["+functionValues.size()+"].",functionValues.size() == exceptedValues.size()); + } + } catch (final FileNotFoundException e) { + fail("Erreur d'analyse (FileNotFoundException)"); + } catch (final IOException e) { + fail("Erreur d'analyse (IOException)"); + } catch (final JFlexException e) { + fail("Erreur d'analyse (JFlexException)"); + } + } +} diff --git a/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/LineOfComment/type_var2d_pdf2d.f90 b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/LineOfComment/type_var2d_pdf2d.f90 new file mode 100644 index 00000000..1d241b68 --- /dev/null +++ b/tests/fr.cnes.analysis.tools.fortran90.metrics.test/src/fr/cnes/analysis/tools/fortran90/metrics/LineOfComment/type_var2d_pdf2d.f90 @@ -0,0 +1,403 @@ +! MD5 of template: 8bd22331adb474e07197fb1405bb97d4 +! ------------------------------------------------------------------------------ +! Copyright (c) 2009-13, Thomas P. Robitaille +! +! All rights reserved. +! +! Redistribution and use in source and binary forms, with or without +! modification, are permitted provided that the following conditions are met: +! +! * Redistributions of source code must retain the above copyright notice, this +! list of conditions and the following disclaimer. +! +! * Redistributions in binary form must reproduce the above copyright notice, +! this list of conditions and the following disclaimer in the documentation +! and/or other materials provided with the distribution. +! +! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +! DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +! FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +! ------------------------------------------------------------------------------ + +module type_var2d_pdf2d + + use lib_array, only : locate, interp2d + use lib_random, only : random + use type_pdf2d, only : pdf2d_sp, pdf2d_dp, sample_pdf2d, set_pdf2d, interpolate_pdf2d + + implicit none + save + + private + + integer,parameter :: sp = selected_real_kind(p=6,r=37) + integer,parameter :: dp = selected_real_kind(p=15,r=307) + + ! The purpose of this class is to implement a 2-d PDF that depends on two + ! other variables that are provided when sampling. The four PDFs neighboring + ! the value requested are then sampled with the same random number, and the + ! resulting value is then interpolated using bilinear interpolation. + + + public :: var2d_pdf2d_dp + type var2d_pdf2d_dp + integer :: nw, nz + real(dp), allocatable :: w(:) + real(dp), allocatable :: z(:) + type(pdf2d_dp), allocatable :: p(:,:) + end type var2d_pdf2d_dp + + + public :: var2d_pdf2d_sp + type var2d_pdf2d_sp + integer :: nw, nz + real(sp), allocatable :: w(:) + real(sp), allocatable :: z(:) + type(pdf2d_sp), allocatable :: p(:,:) + end type var2d_pdf2d_sp + + + public :: set_var2d_pdf2d + interface set_var2d_pdf2d + module procedure set_var2d_pdf2d_sp + module procedure set_var2d_pdf2d_dp + end interface set_var2d_pdf2d + + public :: sample_var2d_pdf2d + interface sample_var2d_pdf2d + module procedure sample_var2d_pdf2d_sp + module procedure sample_var2d_pdf2d_dp + end interface sample_var2d_pdf2d + + public :: interpolate_var2d_pdf2d + interface interpolate_var2d_pdf2d + module procedure interpolate_var2d_pdf2d_sp + module procedure interpolate_var2d_pdf2d_dp + end interface interpolate_var2d_pdf2d + +contains + + + type(var2d_pdf2d_dp) function set_var2d_pdf2d_dp(x, y, w, z, prob) result(v) + + ! Initialize a var2d_pdf2d_dp object + ! + ! This version assumes that all the PDFs are defined on the same grid. + ! We can easily create a version that has different x and y values for + ! each PDF. + ! + ! Parameters + ! ---------- + ! x : 1-d array (size nx) + ! x values in the PDFs + ! y : 1-d array (size ny) + ! y values in the PDFs + ! w : 1-d array (size nw) + ! First set of values that the PDFs are defined for + ! z : 1-d array (size nz) + ! Second set of values that the PDFs are defined for + ! prob : 2-d array (size nx, ny, nw, nz) + ! The probabilities for all the x, y, w, and z values + + implicit none + real(dp),intent(in) :: x(:), y(:), w(:), z(:), prob(:,:,:,:) + integer :: iw,iz + + if(size(prob,1) /= size(x)) stop "incorrect dimensions for prob" + if(size(prob,2) /= size(y)) stop "incorrect dimensions for prob" + if(size(prob,3) /= size(w)) stop "incorrect dimensions for prob" + if(size(prob,4) /= size(z)) stop "incorrect dimensions for prob" + + v%nw = size(w) + v%nz = size(z) + + allocate(v%w(v%nw)) + allocate(v%z(v%nz)) + allocate(v%p(v%nw, v%nz)) + + v%w = w + v%z = z + + do iw=1,v%nw + do iz=1,v%nz + v%p(iw,iz) = set_pdf2d(x, y, prob(:, :, iw, iz)) + end do + end do + + end function set_var2d_pdf2d_dp + + subroutine sample_var2d_pdf2d_dp(w, z, v, x, y) + + ! Sample a var2d_pdf2d_dp object + ! + ! Parameters + ! ---------- + ! w, z : real(dp) + ! The w and z value to sample the PDFs for + ! v : var2d_pdf2d_dp + ! The variable PDF to sample + ! + ! Returns + ! ------- + ! x, y : real(dp) + ! The sampled values + + real(dp),intent(in) :: w, z + type(var2d_pdf2d_dp),intent(in) :: v + real(dp),intent(out) :: x, y + real(dp) :: x11,x12,x21,x22,y11,y12,y21,y22,xi(4) + integer :: iw, iz + integer :: i + + ! Find bin in w and z arrays + iw = locate(v%w, w) + iz = locate(v%z, z) + + ! Sample random values + do i=1,4 + call random(xi(i)) + end do + + ! Sample neighboring PDFs + call sample_pdf2d(v%p(iw, iz), x11, y11, xi_alt=xi) + call sample_pdf2d(v%p(iw+1, iz), x21, y21, xi_alt=xi) + call sample_pdf2d(v%p(iw, iz+1), x12, y12, xi_alt=xi) + call sample_pdf2d(v%p(iw+1, iz+1), x22, y22, xi_alt=xi) + + ! Calculate result using bilinear interpolation + + x = (x11 * (v%w(iw + 1) - w) * (v%z(iz + 1) - z) & + & + x21 * (w - v%w(iw)) * (v%z(iz + 1) - z) & + & + x12 * (v%w(iw + 1) - w) * (z - v%z(iz)) & + & + x22 * (w - v%w(iw)) * (z - v%z(iz))) & + & / (v%w(iw+1) - v%w(iw)) / (v%z(iz+1) - v%z(iz)) + + y = (y11 * (v%w(iw + 1) - w) * (v%z(iz + 1) - z) & + & + y21 * (w - v%w(iw)) * (v%z(iz + 1) - z) & + & + y12 * (v%w(iw + 1) - w) * (z - v%z(iz)) & + & + y22 * (w - v%w(iw)) * (z - v%z(iz))) & + & / (v%w(iw+1) - v%w(iw)) / (v%z(iz+1) - v%z(iz)) + + end subroutine sample_var2d_pdf2d_dp + + + real(dp) function interpolate_var2d_pdf2d_dp(w, z, v, x, y, bounds_error, fill_value) result(prob) + + ! Interpolate a 2-d PDF + ! + ! Parameters + ! ---------- + ! w, z : real(dp) + ! The w and z value to sample the PDFs for + ! v : var2d_pdf2d_dp + ! The variable PDF to interpolate + ! x, y : real(dp) + ! Position at which to interpolate the 2-d PDF + ! bounds_error : logical, optional + ! Whether to raise an error if the interpolation is out of bounds + ! fill_value : real(dp) + ! The value to use for out-of-bounds interpolation if bounds_error = .false. + ! + ! Returns + ! ------- + ! prob : real(dp) + ! The probability at the position requested + + implicit none + + real(dp),intent(in) :: w, z + type(var2d_pdf2d_dp),intent(in) :: v + real(dp),intent(in) :: x, y + logical,intent(in),optional :: bounds_error + real(dp),intent(in),optional :: fill_value + + real(dp) :: p11,p12,p21,p22 + integer :: iw, iz + + ! Find bin in w and z arrays + iw = locate(v%w, w) + iz = locate(v%z, z) + + ! Interpolate neighboring PDFs + p11 = interpolate_pdf2d(v%p(iw, iz), x, y, bounds_error, fill_value) + p21 = interpolate_pdf2d(v%p(iw+1, iz), x, y, bounds_error, fill_value) + p12 = interpolate_pdf2d(v%p(iw, iz+1), x, y, bounds_error, fill_value) + p22 = interpolate_pdf2d(v%p(iw+1, iz+1), x, y, bounds_error, fill_value) + + ! Calculate result using bilinear interpolation + + prob = (p11 * (v%w(iw + 1) - w) * (v%z(iz + 1) - z) & + & + p21 * (w - v%w(iw)) * (v%z(iz + 1) - z) & + & + p12 * (v%w(iw + 1) - w) * (z - v%z(iz)) & + & + p22 * (w - v%w(iw)) * (z - v%z(iz))) & + & / (v%w(iw+1) - v%w(iw)) / (v%z(iz+1) - v%z(iz)) + + end function interpolate_var2d_pdf2d_dp + + + type(var2d_pdf2d_sp) function set_var2d_pdf2d_sp(x, y, w, z, prob) result(v) + + ! Initialize a var2d_pdf2d_sp object + ! + ! This version assumes that all the PDFs are defined on the same grid. + ! We can easily create a version that has different x and y values for + ! each PDF. + ! + ! Parameters + ! ---------- + ! x : 1-d array (size nx) + ! x values in the PDFs + ! y : 1-d array (size ny) + ! y values in the PDFs + ! w : 1-d array (size nw) + ! First set of values that the PDFs are defined for + ! z : 1-d array (size nz) + ! Second set of values that the PDFs are defined for + ! prob : 2-d array (size nx, ny, nw, nz) + ! The probabilities for all the x, y, w, and z values + + implicit none + real(sp),intent(in) :: x(:), y(:), w(:), z(:), prob(:,:,:,:) + integer :: iw,iz + + if(size(prob,1) /= size(x)) stop "incorrect dimensions for prob" + if(size(prob,2) /= size(y)) stop "incorrect dimensions for prob" + if(size(prob,3) /= size(w)) stop "incorrect dimensions for prob" + if(size(prob,4) /= size(z)) stop "incorrect dimensions for prob" + + v%nw = size(w) + v%nz = size(z) + + allocate(v%w(v%nw)) + allocate(v%z(v%nz)) + allocate(v%p(v%nw, v%nz)) + + v%w = w + v%z = z + + do iw=1,v%nw + do iz=1,v%nz + v%p(iw,iz) = set_pdf2d(x, y, prob(:, :, iw, iz)) + end do + end do + + end function set_var2d_pdf2d_sp + + subroutine sample_var2d_pdf2d_sp(w, z, v, x, y) + + ! Sample a var2d_pdf2d_sp object + ! + ! Parameters + ! ---------- + ! w, z : real(sp) + ! The w and z value to sample the PDFs for + ! v : var2d_pdf2d_sp + ! The variable PDF to sample + ! + ! Returns + ! ------- + ! x, y : real(sp) + ! The sampled values + + real(sp),intent(in) :: w, z + type(var2d_pdf2d_sp),intent(in) :: v + real(sp),intent(out) :: x, y + real(sp) :: x11,x12,x21,x22,y11,y12,y21,y22,xi(4) + integer :: iw, iz + integer :: i + + ! Find bin in w and z arrays + iw = locate(v%w, w) + iz = locate(v%z, z) + + ! Sample random values + do i=1,4 + call random(xi(i)) + end do + + ! Sample neighboring PDFs + call sample_pdf2d(v%p(iw, iz), x11, y11, xi_alt=xi) + call sample_pdf2d(v%p(iw+1, iz), x21, y21, xi_alt=xi) + call sample_pdf2d(v%p(iw, iz+1), x12, y12, xi_alt=xi) + call sample_pdf2d(v%p(iw+1, iz+1), x22, y22, xi_alt=xi) + + ! Calculate result using bilinear interpolation + + x = (x11 * (v%w(iw + 1) - w) * (v%z(iz + 1) - z) & + & + x21 * (w - v%w(iw)) * (v%z(iz + 1) - z) & + & + x12 * (v%w(iw + 1) - w) * (z - v%z(iz)) & + & + x22 * (w - v%w(iw)) * (z - v%z(iz))) & + & / (v%w(iw+1) - v%w(iw)) / (v%z(iz+1) - v%z(iz)) + + y = (y11 * (v%w(iw + 1) - w) * (v%z(iz + 1) - z) & + & + y21 * (w - v%w(iw)) * (v%z(iz + 1) - z) & + & + y12 * (v%w(iw + 1) - w) * (z - v%z(iz)) & + & + y22 * (w - v%w(iw)) * (z - v%z(iz))) & + & / (v%w(iw+1) - v%w(iw)) / (v%z(iz+1) - v%z(iz)) + + end subroutine sample_var2d_pdf2d_sp + + + real(sp) function interpolate_var2d_pdf2d_sp(w, z, v, x, y, bounds_error, fill_value) result(prob) + + ! Interpolate a 2-d PDF + ! + ! Parameters + ! ---------- + ! w, z : real(sp) + ! The w and z value to sample the PDFs for + ! v : var2d_pdf2d_sp + ! The variable PDF to interpolate + ! x, y : real(sp) + ! Position at which to interpolate the 2-d PDF + ! bounds_error : logical, optional + ! Whether to raise an error if the interpolation is out of bounds + ! fill_value : real(sp) + ! The value to use for out-of-bounds interpolation if bounds_error = .false. + ! + ! Returns + ! ------- + ! prob : real(sp) + ! The probability at the position requested + + implicit none + + real(sp),intent(in) :: w, z + type(var2d_pdf2d_sp),intent(in) :: v + real(sp),intent(in) :: x, y + logical,intent(in),optional :: bounds_error + real(sp),intent(in),optional :: fill_value + + real(sp) :: p11,p12,p21,p22 + integer :: iw, iz + + ! Find bin in w and z arrays + iw = locate(v%w, w) + iz = locate(v%z, z) + + ! Interpolate neighboring PDFs + p11 = interpolate_pdf2d(v%p(iw, iz), x, y, bounds_error, fill_value) + p21 = interpolate_pdf2d(v%p(iw+1, iz), x, y, bounds_error, fill_value) + p12 = interpolate_pdf2d(v%p(iw, iz+1), x, y, bounds_error, fill_value) + p22 = interpolate_pdf2d(v%p(iw+1, iz+1), x, y, bounds_error, fill_value) + + ! Calculate result using bilinear interpolation + + prob = (p11 * (v%w(iw + 1) - w) * (v%z(iz + 1) - z) & + & + p21 * (w - v%w(iw)) * (v%z(iz + 1) - z) & + & + p12 * (v%w(iw + 1) - w) * (z - v%z(iz)) & + & + p22 * (w - v%w(iw)) * (z - v%z(iz))) & + & / (v%w(iw+1) - v%w(iw)) / (v%z(iz+1) - v%z(iz)) + + end function interpolate_var2d_pdf2d_sp + + +end module type_var2d_pdf2d + diff --git a/tests/fr.cnes.analysis.tools.fortran90.rules.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.fortran90.rules.test/META-INF/MANIFEST.MF index 58f69b70..9604ffb4 100644 --- a/tests/fr.cnes.analysis.tools.fortran90.rules.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.fortran90.rules.test/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES F90 Rules Bundle-SymbolicName: fr.cnes.analysis.tools.fortran90.rules.test -Bundle-Version: 3.0.1.qualifier -Fragment-Host: fr.cnes.analysis.tools.fortran90.rules;bundle-version="3.0.1" +Bundle-Version: 3.1.0.qualifier +Fragment-Host: fr.cnes.analysis.tools.fortran90.rules;bundle-version="3.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: fr.cnes.analysis.tools.fortran90.rules Require-Bundle: org.mockito;bundle-version="1.8.4", diff --git a/tests/fr.cnes.analysis.tools.fortran90.rules.test/pom.xml b/tests/fr.cnes.analysis.tools.fortran90.rules.test/pom.xml index fedaf354..74eb455b 100644 --- a/tests/fr.cnes.analysis.tools.fortran90.rules.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.fortran90.rules.test/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.fortran90.rules.test diff --git a/tests/fr.cnes.analysis.tools.shell.metrics.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.shell.metrics.test/META-INF/MANIFEST.MF index 6f7aed35..61fc6462 100644 --- a/tests/fr.cnes.analysis.tools.shell.metrics.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.shell.metrics.test/META-INF/MANIFEST.MF @@ -2,9 +2,9 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES SH Metrics Bundle-SymbolicName: fr.cnes.analysis.tools.shell.metrics.test -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Vendor: CNES -Fragment-Host: fr.cnes.analysis.tools.shell.metrics;bundle-version="3.0.1" +Fragment-Host: fr.cnes.analysis.tools.shell.metrics;bundle-version="3.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: fr.cnes.analysis.tools.shell.metrics Require-Bundle: org.mockito;bundle-version="1.8.4", diff --git a/tests/fr.cnes.analysis.tools.shell.metrics.test/pom.xml b/tests/fr.cnes.analysis.tools.shell.metrics.test/pom.xml index 6a9370ff..0334fee3 100644 --- a/tests/fr.cnes.analysis.tools.shell.metrics.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.shell.metrics.test/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.shell.metrics.test diff --git a/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/AllTests.java b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/AllTests.java index e1c889da..201c3391 100755 --- a/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/AllTests.java +++ b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/AllTests.java @@ -12,6 +12,7 @@ import fr.cnes.analysis.tools.shell.metrics.MET.ComplexitySimplified.TestSHMETComplexitySimplified; import fr.cnes.analysis.tools.shell.metrics.MET.LineOfCode.TestSHMETLineOfCode; +import fr.cnes.analysis.tools.shell.metrics.MET.LineOfComment.TestSHMETLineOfComment; import fr.cnes.analysis.tools.shell.metrics.MET.Nesting.TestSHMETNesting; import fr.cnes.analysis.tools.shell.metrics.MET.RatioComment.TestSHMETRatioComment; @@ -22,6 +23,7 @@ TestSHMETComplexitySimplified.class, TestSHMETNesting.class, TestSHMETLineOfCode.class, + TestSHMETLineOfComment.class, TestSHMETRatioComment.class}) public class AllTests { } diff --git a/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/LineOfComment/TestSHMETLineOfComment.java b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/LineOfComment/TestSHMETLineOfComment.java new file mode 100644 index 00000000..b2471705 --- /dev/null +++ b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/LineOfComment/TestSHMETLineOfComment.java @@ -0,0 +1,146 @@ +/************************************************************************************************/ +/* i-Code CNES is a static code analyzer. */ +/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/************************************************************************************************/ + +package fr.cnes.analysis.tools.shell.metrics.MET.LineOfComment; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.core.runtime.FileLocator; +import org.junit.Test; + +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import fr.cnes.analysis.tools.shell.metrics.SHMETLineOfComment; +import fr.cnes.analysis.tools.shell.metrics.TestUtils; + +/** + * This class aims to test Don.Declaration rule. There are 2 functions in this + * class. The first one verifies that an error in a file is detected whenever + * there is one, the other verifies that nothing is detected when there's no + * error. + * + */ +public class TestSHMETLineOfComment { + + /** + * This test verifies that an error can be detected. + */ + @Test + public void testRunWithError() { + + try { + // Initializing rule and getting error file. + final AbstractChecker metric = new SHMETLineOfComment(); + final String fileName = "nvm.sh"; + final File file = new File( + FileLocator.resolve(this.getClass().getResource(fileName)).getFile()); + + // Defining file in the rule instantiation. + metric.setContribution(TestUtils.getContribution("", "")); + metric.setInputFile(file); + + // We verify that the metric value detected is the right one. + // Get the list and verify each value + final List checkResults = metric.run(); + CheckResult fileValue = null; + for (CheckResult check : checkResults) { + if (check.getLocation()==null || check.getLocation().isEmpty()) { + fileValue = check; + checkResults.remove(checkResults.indexOf(check)); + } + } + if (fileValue == null) { + fail("Erreur : Aucun r�sultat sur le fichier trouv�."); + } else { + + assertTrue(fileValue.getFile().getName().equals(fileName)); + Float exceptedFileValue = (float)246; + assertTrue("Test except a file value of ["+Math.round(exceptedFileValue) +"] while metric computed ["+Math.round(fileValue.getValue())+"].",Math.round(fileValue.getValue()) == Math.round(exceptedFileValue)); + + + final List functionValues = checkResults; + Map exceptedValues = new TreeMap<>(); + exceptedValues.put("MAIN PROGRAM",(float)246); + exceptedValues.put("nvm_add_iojs_prefix",(float)4); + exceptedValues.put("nvm_alias",(float)4); + exceptedValues.put("nvm_alias_path",(float)4); + exceptedValues.put("nvm_binary_available",(float)4); + exceptedValues.put("nvm_cd",(float)5); + exceptedValues.put("nvm_clang_version",(float)4); + exceptedValues.put("nvm_command_info",(float)4); + exceptedValues.put("nvm_curl_libz_support",(float)4); + exceptedValues.put("nvm_curl_use_compression",(float)4); + exceptedValues.put("nvm_curl_version",(float)4); + exceptedValues.put("nvm_download",(float)6); + exceptedValues.put("nvm_ensure_version_installed",(float)4); + exceptedValues.put("nvm_ensure_version_prefix",(float)3); + exceptedValues.put("nvm_err",(float)4); + exceptedValues.put("nvm_find_nvmrc",(float)4); + exceptedValues.put("nvm_find_up",(float)5); + exceptedValues.put("nvm_format_version",(float)2); + exceptedValues.put("nvm_get_latest",(float)4); + exceptedValues.put("nvm_grep",(float)4); + exceptedValues.put("nvm_has",(float)4); + exceptedValues.put("nvm_has_colors",(float)4); + exceptedValues.put("nvm_has_non_aliased",(float)4); + exceptedValues.put("nvm_has_system_iojs",(float)4); + exceptedValues.put("nvm_has_system_node",(float)4); + exceptedValues.put("nvm_install_latest_npm",(float)5); + exceptedValues.put("nvm_iojs_prefix",(float)4); + exceptedValues.put("nvm_is_alias",(float)6); + exceptedValues.put("nvm_is_iojs_version",(float)3); + exceptedValues.put("nvm_is_valid_version",(float)4); + exceptedValues.put("nvm_is_version_installed",(float)3); + exceptedValues.put("nvm_ls_current",(float)4); + exceptedValues.put("nvm_ls_remote_index_tab",(float)5); + exceptedValues.put("nvm_ls_remote_iojs",(float)4); + exceptedValues.put("nvm_make_alias",(float)4); + exceptedValues.put("nvm_node_prefix",(float)4); + exceptedValues.put("nvm_normalize_version",(float)3); + exceptedValues.put("nvm_num_version_groups",(float)4); + exceptedValues.put("nvm_prepend_path",(float)3); + exceptedValues.put("nvm_print_alias_path",(float)3); + exceptedValues.put("nvm_print_formatted_alias",(float)3); + exceptedValues.put("nvm_print_npm_version",(float)4); + exceptedValues.put("nvm_rc_version",(float)5); + exceptedValues.put("nvm_remote_version",(float)4); + exceptedValues.put("nvm_remote_versions",(float)4); + exceptedValues.put("nvm_resolve_alias",(float)4); + exceptedValues.put("nvm_resolve_local_alias",(float)4); + exceptedValues.put("nvm_strip_iojs_prefix",(float)4); + exceptedValues.put("nvm_strip_path",(float)3); + exceptedValues.put("nvm_tree_contains_path",(float)4); + exceptedValues.put("nvm_version",(float)6); + exceptedValues.put("nvm_version_dir",(float)4); + exceptedValues.put("nvm_version_greater",(float)3); + exceptedValues.put("nvm_version_greater_than_or_equal_to",(float)4); + exceptedValues.put("nvm_version_path",(float)4); + exceptedValues.put("vm_ls_remote",(float)4); + for(CheckResult metricValue : functionValues){ + assertTrue("Test do not excepts function : "+metricValue.getLocation()+".",exceptedValues.containsKey(metricValue.getLocation())); + assertTrue("Test excepts value of ["+Math.round(exceptedValues.get(metricValue.getLocation()))+"] while metric computed ["+Math.round(metricValue.getValue())+"] for the function "+metricValue.getLocation()+".",Math.round(metricValue.getValue()) == Math.round(exceptedValues.get(metricValue.getLocation()))); + } + assertTrue("Test excepts "+exceptedValues.size()+" functions computed for the file while the metric computed ["+functionValues.size()+"].",functionValues.size() == exceptedValues.size()); + + } + } catch (final FileNotFoundException e) { + fail("Erreur d'analyse (FileNotFoundException)"); + } catch (final IOException e) { + fail("Erreur d'analyse (IOException)"); + } catch (final JFlexException e) { + fail("Erreur d'analyse (JFlexException)"); + } + } +} diff --git a/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/LineOfComment/nvm.sh b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/LineOfComment/nvm.sh new file mode 100644 index 00000000..90bc287b --- /dev/null +++ b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/LineOfComment/nvm.sh @@ -0,0 +1,1180 @@ +# The MIT License (MIT) +# +# Copyright (c) 2010-2017 Tim Caswell +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Node Version Manager partially edited to be parsed by i-Code CNES analyzer for testing. +# Please find the original project on : https://github.com/creationix/nvm/blob/master/nvm.sh +# Implemented by Tim Caswell +# with much bash help from Matthew Ranney +# +# MAIN PROGRAM : +# - SH.MET.ComplexitySimplified = 5; +# - SH.MET.LineOfCode = 838 +# - SH.MET.Nesting = 2 +# - SH.MET.RatioComment = 22.41% + +NVM_SCRIPT_SOURCE="$_" + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_cd() { + # shellcheck disable=SC1001,SC2164 + \cd "$@" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_err() { + >&2 nvm_echo "$@" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_grep() { + GREP_OPTIONS='' command grep "$@" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_has() { + type "${1-}" > /dev/null 2>&1 +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_has_non_aliased() { + nvm_has "${1-}" && ! nvm_is_alias "${1-}" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_is_alias() { + # this is intentionally not "command alias" so it works in zsh. + # shellcheck disable=SC1001 + \alias "${1-}" > /dev/null 2>&1 +} + +#SH.MET.RatioComment = 15.00 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=17 +#SH.MET.ComplexitySimplified = 6; +nvm_command_info() { + local COMMAND + local INFO + COMMAND="${1}" + if type "${COMMAND}" | command grep -q hashed; then + echo "test"; + elif type "${COMMAND}" | command grep -q aliased; then + echo "test"; + elif type "${COMMAND}" | command grep -q "^${COMMAND} is an alias for"; then + echo "test"; + elif type "${COMMAND}" | command grep -q "^${COMMAND} is \/"; then + echo "test"; + else + echo "test"; + fi + nvm_echo "${INFO}" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=7 +#SH.MET.ComplexitySimplified = 2; +nvm_has_colors() { + local NVM_COLORS + if nvm_has tput; then + NVM_COLORS="$(tput -T "${TERM:-vt100}" colors)" + fi + [ "${NVM_COLORS:--1}" -ge 8 ] +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_curl_libz_support() { + curl -V 2>/dev/null | nvm_grep "^Features:" | nvm_grep -q "libz" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode= 3; +#SH.MET.ComplexitySimplified = 1; +nvm_curl_use_compression() { + nvm_curl_libz_support && nvm_version_greater_than_or_equal_to "$(nvm_curl_version)" 7.21.0; +} + +#SH.MET.RatioComment = 13.04 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=20 +#SH.MET.ComplexitySimplified = 6; +nvm_get_latest() { + local NVM_LATEST_URL + local CURL_COMPRESSED_FLAG + if nvm_has "curl"; then + if nvm_curl_use_compression; then + CURL_COMPRESSED_FLAG="--compressed" + fi + NVM_LATEST_URL="$(curl ${CURL_COMPRESSED_FLAG:-} -q -w "%{url_effective}\n" -L -s -S http://latest.nvm.sh -o /dev/null)" + elif nvm_has "wget"; then + NVM_LATEST_URL="$(wget http://latest.nvm.sh --server-response -O /dev/null 2>&1 | command awk '/^ Location: /{DEST=$2} END{ print DEST }')" + else + nvm_err 'nvm needs curl or wget to proceed.' + return 1 + fi + if [ -z "${NVM_LATEST_URL}" ]; then + nvm_err "http://latest.nvm.sh did not redirect to the latest release on GitHub" + return 2 + fi + nvm_echo "${NVM_LATEST_URL##*/}" +} + +#SH.MET.RatioComment = 20.83 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=19 +#SH.MET.ComplexitySimplified = 4; +nvm_download() { + local CURL_COMPRESSED_FLAG + if nvm_has "curl"; then + if nvm_curl_use_compression; then + CURL_COMPRESSED_FLAG="--compressed" + fi + curl --fail ${CURL_COMPRESSED_FLAG:-} -q "$@" + elif nvm_has "wget"; then + # Emulate curl with wget + ARGS=$(nvm_echo "$@" | command sed -e 's/--progress-bar /--progress=bar /' \ + -e 's/--compressed //' \ + -e 's/--fail //' \ + -e 's/-L //' \ + -e 's/-I /--server-response /' \ + -e 's/-s /-q /' \ + -e 's/-o /-O /' \ + -e 's/-C - /-c /') + # shellcheck disable=SC2086 + eval wget $ARGS + fi +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_has_system_node() { + [ "$(nvm deactivate >/dev/null 2>&1 && command -v node)" != '' ] +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_has_system_iojs() { + [ "$(nvm deactivate >/dev/null 2>&1 && command -v iojs)" != '' ] +} + +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_is_version_installed() { + [ -n "${1-}" ] && [ -d "$(nvm_version_path "${1-}" 2> /dev/null)" ] +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=5 +#SH.MET.ComplexitySimplified = 2; +nvm_print_npm_version() { + if nvm_has "npm"; then + command printf " (npm v$(npm --version 2>/dev/null))" + fi +} + +#SH.MET.RatioComment = 6.06 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=62 +#SH.MET.ComplexitySimplified = 16; +nvm_install_latest_npm() { + nvm_echo 'Attempting to upgrade to the latest working version of npm...' + local NODE_VERSION + NODE_VERSION="$(nvm_strip_iojs_prefix "$(nvm_ls_current)")" + if [ "${NODE_VERSION}" = 'system' ]; then + NODE_VERSION="$(node --version)" + elif [ "${NODE_VERSION}" = 'none' ]; then + nvm_echo "Detected node version ${NODE_VERSION}, npm version v${NPM_VERSION}" + NODE_VERSION='' + fi + if [ -z "${NODE_VERSION}" ]; then + nvm_err 'Unable to obtain node version.' + return 1 + fi + local NPM_VERSION + NPM_VERSION="$(npm --version 2>/dev/null)" + if [ -z "${NPM_VERSION}" ]; then + nvm_err 'Unable to obtain npm version.' + return 2 + fi + + local NVM_NPM_CMD + NVM_NPM_CMD='npm' + if [ "${NVM_DEBUG-}" = 1 ]; then + nvm_echo "Detected node version ${NODE_VERSION}, npm version v${NPM_VERSION}" + NVM_NPM_CMD='echo npm' + fi + + local NVM_IS_0_6 + NVM_IS_0_6=0 + if nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 0.6.0 && nvm_version_greater 0.7.0 "${NODE_VERSION}"; then + NVM_IS_0_6=1 + fi + local NVM_IS_0_9 + NVM_IS_0_9=0 + if nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 0.9.0 && nvm_version_greater 0.10.0 "${NODE_VERSION}"; then + NVM_IS_0_9=1 + fi + + if [ $NVM_IS_0_6 -eq 1 ]; then + nvm_echo '* `node` v0.6.x can only upgrade to `npm` v1.3.x' + $NVM_NPM_CMD install -g npm@1.3 + elif [ $NVM_IS_0_9 -eq 0 ]; then + # node 0.9 breaks here, for some reason + if nvm_version_greater_than_or_equal_to "${NPM_VERSION}" 1.0.0 && nvm_version_greater 2.0.0 "${NPM_VERSION}"; then + nvm_echo '* `npm` v1.x needs to first jump to `npm` v1.4.28 to be able to upgrade further' + $NVM_NPM_CMD install -g npm@1.4.28 + elif nvm_version_greater_than_or_equal_to "${NPM_VERSION}" 2.0.0 && nvm_version_greater 3.0.0 "${NPM_VERSION}"; then + nvm_echo '* `npm` v2.x needs to first jump to the latest v2 to be able to upgrade further' + $NVM_NPM_CMD install -g npm@2 + fi + fi + + if [ $NVM_IS_0_9 -eq 1 ] || [ $NVM_IS_0_6 -eq 1 ]; then + nvm_echo '* node v0.6 and v0.9 are unable to upgrade further' + elif nvm_version_greater 1.0.0 "${NODE_VERSION}"; then + nvm_echo '* `npm` v4.5.x is the last version that works on `node` versions below v1.0.0' + $NVM_NPM_CMD install -g npm@4.5 + elif nvm_version_greater 4.0.0 "${NODE_VERSION}"; then + nvm_echo '* `npm` v5 and higher do not work on `node` versions below v4.0.0' + $NVM_NPM_CMD install -g npm@4 + elif [ $NVM_IS_0_9 -eq 0 ] && [ $NVM_IS_0_6 -eq 0 ]; then + nvm_echo '* Installing latest `npm`; if this does not work on your node version, please report a bug!' + $NVM_NPM_CMD install -g npm + fi + nvm_echo "* npm upgraded to: v$(npm --version 2>/dev/null)" +} + +# Make zsh glob matching behave same as bash +# This fixes the "zsh: no matches found" errors +if [ -z "${NVM_CD_FLAGS-}" ]; then + export NVM_CD_FLAGS='' +fi +if nvm_has "unsetopt"; then + unsetopt nomatch 2>/dev/null + NVM_CD_FLAGS="-q" +fi + +# Auto detect the NVM_DIR when not set +if [ -z "${NVM_DIR-}" ]; then + # shellcheck disable=SC2128 + if [ -n "${BASH_SOURCE-}" ]; then + # shellcheck disable=SC2169 + NVM_SCRIPT_SOURCE="${BASH_SOURCE[0]}" + fi + # shellcheck disable=SC1001 + NVM_DIR="$(nvm_cd ${NVM_CD_FLAGS} "$(dirname "${NVM_SCRIPT_SOURCE:-$0}")" > /dev/null && \pwd)" + export NVM_DIR +fi +unset NVM_SCRIPT_SOURCE 2> /dev/null + +#SH.MET.RatioComment = 15.79 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=16 +#SH.MET.ComplexitySimplified = 4; +nvm_tree_contains_path() { + local tree + tree="${1-}" + local node_path + node_path="${2-}" + + if [ "@${tree}@" = "@@" ] || [ "@${node_path}@" = "@@" ]; then + nvm_err "both the tree and the node path are required" + return 2 + fi + + local pathdir + pathdir=$(dirname "${node_path}") + while [ "${pathdir}" != "" ] && [ "${pathdir}" != "." ] && [ "${pathdir}" != "/" ] && [ "${pathdir}" != "${tree}" ]; do + pathdir=$(dirname "${pathdir}") + done + [ "${pathdir}" = "${tree}" ] +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=8 +#SH.MET.ComplexitySimplified = 3; +# Traverse up in directory tree to find containing folder +nvm_find_up() { + local path + path="${PWD}" + while [ "${path}" != "" ] && [ ! -f "${path}/${1-}" ]; do + path=${path%/*} + done + nvm_echo "${path}" +} + + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=7 +#SH.MET.ComplexitySimplified = 2; +nvm_find_nvmrc() { + local dir + dir="$(nvm_find_up '.nvmrc')" + if [ -e "${dir}/.nvmrc" ]; then + nvm_echo "${dir}/.nvmrc" + fi +} + +#SH.MET.RatioComment = 21.05 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=15 +#SH.MET.ComplexitySimplified = 3; +# Obtain nvm version from rc file +nvm_rc_version() { + export NVM_RC_VERSION='' + local NVMRC_PATH + NVMRC_PATH="$(nvm_find_nvmrc)" + if [ ! -e "${NVMRC_PATH}" ]; then + nvm_err "No .nvmrc file found" + return 1 + fi + read -r NVM_RC_VERSION < "${NVMRC_PATH}" || printf '' + if [ ! -n "${NVM_RC_VERSION}" ]; then + nvm_err "Warning: empty .nvmrc file found at \"${NVMRC_PATH}\"" + return 2 + fi + nvm_echo "Found '${NVMRC_PATH}' with version <${NVM_RC_VERSION}>" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_clang_version() { + clang --version | command awk '{ if ($2 == "version") print $3; else if ($3 == "version") print $4 }' | command sed 's/-.*$//g' +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_curl_version() { + curl -V | command awk '{ if ($1 == "curl") print $2 }' | command sed 's/-.*$//g' +} + +#SH.MET.RatioComment = 12.5 +#SH.MET.LineOfCode=14 +#SH.MET.ComplexitySimplified = 1 +nvm_version_greater() { + command awk 'BEGIN { + if (ARGV[1] == "" || ARGV[2] == "") exit(1) + split(ARGV[1], a, /\./); + split(ARGV[2], b, /\./); + for (i=1; i<=3; i++) { + if (a[i] && a[i] !~ /^[0-9]+$/) exit(2); + if (b[i] && b[i] !~ /^[0-9]+$/) { exit(0); } + if (a[i] < b[i]) exit(3); + else if (a[i] > b[i]) exit(0); + } + exit(4) + }' "${1#v}" "${2#v}"; +} + +#SH.MET.RatioComment = 18.75 +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=13 +#SH.MET.ComplexitySimplified = 1 +nvm_version_greater_than_or_equal_to() { + command awk 'BEGIN { + if (ARGV[1] == "" || ARGV[2] == "") exit(1) + split(ARGV[1], a, /\./); + split(ARGV[2], b, /\./); + for (i=1; i<=3; i++) { + if (a[i] && a[i] !~ /^[0-9]+$/) exit(2); + if (a[i] < b[i]) exit(3); + else if (a[i] > b[i]) exit(0); + } + exit(0) + }' "${1#v}" "${2#v}"; +} + +#SH.MET.RatioComment = 17.65 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=14 +#SH.MET.ComplexitySimplified = 5 +nvm_version_dir() { + local NVM_WHICH_DIR + NVM_WHICH_DIR="${1-}" + if [ -z "${NVM_WHICH_DIR}" ] || [ "${NVM_WHICH_DIR}" = "new" ]; then + nvm_echo "${NVM_DIR}/versions/node" + elif [ "_${NVM_WHICH_DIR}" = "_iojs" ]; then + nvm_echo "${NVM_DIR}/versions/io.js" + elif [ "_${NVM_WHICH_DIR}" = "_old" ]; then + nvm_echo "${NVM_DIR}" + else + nvm_err 'unknown version dir' + return 3 + fi +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_alias_path() { + nvm_echo "$(nvm_version_dir old)/alias" +} + +#SH.MET.RatioComment = 17.65 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=14 +#SH.MET.ComplexitySimplified = 5; +nvm_version_path() { + local VERSION + VERSION="${1-}" + if [ -z "${VERSION}" ]; then + nvm_err 'version is required' + return 3 + elif nvm_is_iojs_version "${VERSION}"; then + nvm_echo "$(nvm_version_dir iojs)/$(nvm_strip_iojs_prefix "${VERSION}")" + elif nvm_version_greater 0.12.0 "${VERSION}"; then + nvm_echo "$(nvm_version_dir old)/${VERSION}" + else + nvm_echo "$(nvm_version_dir new)/${VERSION}" + fi +} + +#SH.MET.RatioComment = 9.68 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=28 +#SH.MET.ComplexitySimplified = 6; +nvm_ensure_version_installed() { + local PROVIDED_VERSION + PROVIDED_VERSION="${1-}" + if [ "${PROVIDED_VERSION}" = 'system' ]; then + if nvm_has_system_iojs || nvm_has_system_node; then + return 0 + fi + nvm_err "N/A: no system version of node/io.js is installed." + return 1 + fi + local LOCAL_VERSION + local EXIT_CODE + LOCAL_VERSION="$(nvm_version "${PROVIDED_VERSION}")" + EXIT_CODE="$?" + local NVM_VERSION_DIR + if [ "${EXIT_CODE}" != "0" ] || ! nvm_is_version_installed "${LOCAL_VERSION}"; then + if VERSION="$(nvm_resolve_alias "${PROVIDED_VERSION}")"; then + nvm_err "N/A: version \"${PROVIDED_VERSION} -> ${VERSION}\" is not yet installed." + else + local PREFIXED_VERSION + PREFIXED_VERSION="$(nvm_ensure_version_prefix "${PROVIDED_VERSION}")" + nvm_err "N/A: version \"${PREFIXED_VERSION:-$PROVIDED_VERSION}\" is not yet installed." + fi + nvm_err "" + nvm_err "You need to run \"nvm install ${PROVIDED_VERSION}\" to install it before using it." + return 1 + fi +} +#SH.MET.RatioComment = 16.67 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=25 +#SH.MET.ComplexitySimplified = 5 +# Expand a version using the version cache +nvm_version() { + local PATTERN + PATTERN="${1-}" + local VERSION + # The default version is the current one + if [ -z "${PATTERN}" ]; then + PATTERN='current' + fi + + if [ "${PATTERN}" = "current" ]; then + nvm_ls_current + return $? + fi + + local NVM_NODE_PREFIX + NVM_NODE_PREFIX="$(nvm_node_prefix)" + case "_${PATTERN}" in + "_${NVM_NODE_PREFIX}" | "_${NVM_NODE_PREFIX}-") + PATTERN="stable" + ;; + esac + VERSION="$(nvm_ls "${PATTERN}" | command tail -1)" + if [ -z "${VERSION}" ] || [ "_${VERSION}" = "_N/A" ]; then + nvm_echo "N/A" + return 3; + fi + nvm_echo "${VERSION}" +} + +#SH.MET.RatioComment = 9.67 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=28 +#SH.MET.ComplexitySimplified = 10; +nvm_remote_version() { + local PATTERN + PATTERN="${1-}" + local VERSION + if nvm_validate_implicit_alias "${PATTERN}" 2> /dev/null ; then + case "${PATTERN}" in + "$(nvm_iojs_prefix)") + VERSION="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote_iojs | command tail -1)" &&: + ;; + *) + VERSION="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote "${PATTERN}")" &&: + ;; + esac + else + VERSION="$(NVM_LTS="${NVM_LTS-}" nvm_remote_versions "${PATTERN}" | command tail -1)" + fi + if [ -n "${NVM_VERSION_ONLY-}" ]; then + command awk 'BEGIN { + n = split(ARGV[1], a); + print a[1] + }' "${VERSION}" + else + nvm_echo "${VERSION}" + fi + if [ "${VERSION}" = 'N/A' ]; then + return 3 + fi +} + +#SH.MET.RatioComment = 5 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=57 +nvm_remote_versions() { + local NVM_IOJS_PREFIX + NVM_IOJS_PREFIX="$(nvm_iojs_prefix)" + local NVM_NODE_PREFIX + NVM_NODE_PREFIX="$(nvm_node_prefix)" + + local PATTERN + PATTERN="${1-}" + + local NVM_FLAVOR + if [ -n "${NVM_LTS-}" ]; then + NVM_FLAVOR="${NVM_NODE_PREFIX}" + fi + + case "${PATTERN}" in + "${NVM_IOJS_PREFIX}" | "io.js") + NVM_FLAVOR="${NVM_IOJS_PREFIX}" + unset PATTERN + ;; + "${NVM_NODE_PREFIX}") + NVM_FLAVOR="${NVM_NODE_PREFIX}" + unset PATTERN + ;; + esac + + if nvm_validate_implicit_alias "${PATTERN-}" 2> /dev/null ; then + nvm_err 'Implicit aliases are not supported in nvm_remote_versions.' + return 1 + fi + + local NVM_LS_REMOTE_EXIT_CODE + NVM_LS_REMOTE_EXIT_CODE=0 + local NVM_LS_REMOTE_PRE_MERGED_OUTPUT + NVM_LS_REMOTE_PRE_MERGED_OUTPUT='' + local NVM_LS_REMOTE_POST_MERGED_OUTPUT + NVM_LS_REMOTE_POST_MERGED_OUTPUT='' + if [ -z "${NVM_FLAVOR-}" ] || [ "${NVM_FLAVOR-}" = "${NVM_NODE_PREFIX}" ]; then + local NVM_LS_REMOTE_OUTPUT + NVM_LS_REMOTE_OUTPUT=$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote "${PATTERN-}") &&: + NVM_LS_REMOTE_EXIT_CODE=$? + # split output into two + NVM_LS_REMOTE_PRE_MERGED_OUTPUT="${NVM_LS_REMOTE_OUTPUT%%v4\.0\.0*}" + NVM_LS_REMOTE_POST_MERGED_OUTPUT="${NVM_LS_REMOTE_OUTPUT#$NVM_LS_REMOTE_PRE_MERGED_OUTPUT}" + fi + + local NVM_LS_REMOTE_IOJS_EXIT_CODE + NVM_LS_REMOTE_IOJS_EXIT_CODE=0 + local NVM_LS_REMOTE_IOJS_OUTPUT + if [ -z "${NVM_LTS-}" ] && ( \ + [ -z "${NVM_FLAVOR-}" ] || [ "${NVM_FLAVOR-}" = "${NVM_IOJS_PREFIX}" ] \ + ); then + NVM_LS_REMOTE_IOJS_OUTPUT=$(nvm_ls_remote_iojs "${PATTERN-}") &&: + NVM_LS_REMOTE_IOJS_EXIT_CODE=$? + fi + + VERSIONS="$(nvm_echo "${NVM_LS_REMOTE_PRE_MERGED_OUTPUT} +${NVM_LS_REMOTE_IOJS_OUTPUT} +${NVM_LS_REMOTE_POST_MERGED_OUTPUT}" | nvm_grep -v "N/A" | command sed '/^$/d')" + + if [ -z "${VERSIONS}" ]; then + nvm_echo 'N/A' + return 3 + fi + nvm_echo "${VERSIONS}" + return $NVM_LS_REMOTE_EXIT_CODE || $NVM_LS_REMOTE_IOJS_EXIT_CODE +} + +#SH.MET.RatioComment = 15.79 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=16 +#SH.MET.ComplexitySimplified = 4; +nvm_is_valid_version() { + if nvm_validate_implicit_alias "${1-}" 2> /dev/null; then + return 0 + fi + case "${1-}" in + "$(nvm_iojs_prefix)" | \ + "$(nvm_node_prefix)") + return 0 + ;; + *) + local VERSION + VERSION="$(nvm_strip_iojs_prefix "${1-}")" + nvm_version_greater_than_or_equal_to "${VERSION}" 0 + ;; + esac +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=7 +nvm_normalize_version() { + command awk 'BEGIN { + split(ARGV[1], a, /\./); + printf "%d%06d%06d\n", a[1], a[2], a[3]; + exit; + }' "${1#v}" +} + +#SH.MET.RatioComment = 15.38 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=11 +nvm_ensure_version_prefix() { + local NVM_VERSION + NVM_VERSION="$(nvm_strip_iojs_prefix "${1-}" | command sed -e 's/^\([0-9]\)/v\1/g')" + if nvm_is_iojs_version "${1-}"; then + nvm_add_iojs_prefix "${NVM_VERSION}" + else + nvm_echo "${NVM_VERSION}" + fi +} + +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=11 +nvm_format_version() { + local VERSION + VERSION="$(nvm_ensure_version_prefix "${1-}")" + local NUM_GROUPS + NUM_GROUPS="$(nvm_num_version_groups "${VERSION}")" + if [ "${NUM_GROUPS}" -lt 3 ]; then + nvm_format_version "${VERSION%.}.0" + else + nvm_echo "${VERSION}" | command cut -f1-3 -d. + fi +} + +#SH.MET.RatioComment = 16.67 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=15 +nvm_num_version_groups() { + local VERSION + VERSION="${1-}" + VERSION="${VERSION#v}" + VERSION="${VERSION%.}" + if [ -z "${VERSION}" ]; then + nvm_echo "0" + return + fi + local NVM_NUM_DOTS + NVM_NUM_DOTS=$(nvm_echo "${VERSION}" | command sed -e 's/[^\.]//g') + local NVM_NUM_GROUPS + NVM_NUM_GROUPS=".${NVM_NUM_DOTS}" # add extra dot, since it's (n - 1) dots at this point + nvm_echo "${#NVM_NUM_GROUPS}" +} + +#SH.MET.RatioComment = 13.33 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=13 +nvm_strip_path() { + if [ -z "${NVM_DIR-}" ]; then + nvm_err '${NVM_DIR} not set!' + return 1 + fi + nvm_echo "${1-}" | command sed \ + -e "s#${NVM_DIR}/[^/]*${2-}[^:]*:##g" \ + -e "s#:${NVM_DIR}/[^/]*${2-}[^:]*##g" \ + -e "s#${NVM_DIR}/[^/]*${2-}[^:]*##g" \ + -e "s#${NVM_DIR}/versions/[^/]*/[^/]*${2-}[^:]*:##g" \ + -e "s#:${NVM_DIR}/versions/[^/]*/[^/]*${2-}[^:]*##g" \ + -e "s#${NVM_DIR}/versions/[^/]*/[^/]*${2-}[^:]*##g" +} + +#SH.MET.RatioComment = NaN +#SH.MET.LineOfCode=7 +#SH.MET.ComplexitySimplified = 3; +nvm_prepend_path() { + if [ -z "${1-}" ]; then + nvm_echo "${2-}" + else + nvm_echo "${2-}:${1-}" + fi +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +nvm_binary_available() { + # binaries started with node 0.8.6 + nvm_version_greater_than_or_equal_to "$(nvm_strip_iojs_prefix "${1-}")" v0.8.6 +} + +#SH.MET.RatioComment = 3.4 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=56 +nvm_print_formatted_alias() { + local ALIAS + ALIAS="${1-}" + local DEST + DEST="${2-}" + local VERSION + VERSION="${3-}" + if [ -z "${VERSION}" ]; then + VERSION="$(nvm_version "${DEST}")" ||: + fi + local VERSION_FORMAT + local ALIAS_FORMAT + local DEST_FORMAT + ALIAS_FORMAT='%s' + DEST_FORMAT='%s' + VERSION_FORMAT='%s' + local NEWLINE + NEWLINE="\n" + if [ "_${DEFAULT}" = '_true' ]; then + NEWLINE=" (default)\n" + fi + local ARROW + ARROW='->' + if [ -z "${NVM_NO_COLORS}" ] && nvm_has_colors; then + ARROW='\033[0;90m->\033[0m' + if [ "_${DEFAULT}" = '_true' ]; then + NEWLINE=" \033[0;37m(default)\033[0m\n" + fi + if [ "_${VERSION}" = "_${NVM_CURRENT-}" ]; then + ALIAS_FORMAT='\033[0;32m%s\033[0m' + DEST_FORMAT='\033[0;32m%s\033[0m' + VERSION_FORMAT='\033[0;32m%s\033[0m' + elif nvm_is_version_installed "${VERSION}"; then + ALIAS_FORMAT='\033[0;34m%s\033[0m' + DEST_FORMAT='\033[0;34m%s\033[0m' + VERSION_FORMAT='\033[0;34m%s\033[0m' + elif [ "${VERSION}" = '∞' ] || [ "${VERSION}" = 'N/A' ]; then + ALIAS_FORMAT='\033[1;31m%s\033[0m' + DEST_FORMAT='\033[1;31m%s\033[0m' + VERSION_FORMAT='\033[1;31m%s\033[0m' + fi + if [ "_${NVM_LTS-}" = '_true' ]; then + ALIAS_FORMAT='\033[1;33m%s\033[0m' + fi + if [ "_${DEST%/*}" = "_lts" ]; then + DEST_FORMAT='\033[1;33m%s\033[0m' + fi + elif [ "_$VERSION" != '_∞' ] && [ "_$VERSION" != '_N/A' ]; then + VERSION_FORMAT='%s *' + fi + if [ "${DEST}" = "${VERSION}" ]; then + command printf -- "${ALIAS_FORMAT} ${ARROW} ${VERSION_FORMAT}${NEWLINE}" "${ALIAS}" "${DEST}" + else + command printf -- "${ALIAS_FORMAT} ${ARROW} ${DEST_FORMAT} (${ARROW} ${VERSION_FORMAT})${NEWLINE}" "${ALIAS}" "${DEST}" "${VERSION}" + fi +} + +#SH.MET.RatioComment = 12.5 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=21 +nvm_print_alias_path() { + local NVM_ALIAS_DIR + NVM_ALIAS_DIR="${1-}" + if [ -z "${NVM_ALIAS_DIR}" ]; then + nvm_err 'An alias dir is required.' + return 1 + fi + local ALIAS_PATH + ALIAS_PATH="${2-}" + if [ -z "${ALIAS_PATH}" ]; then + nvm_err 'An alias path is required.' + return 2 + fi + local ALIAS + ALIAS="${ALIAS_PATH##${NVM_ALIAS_DIR}\/}" + local DEST + DEST="$(nvm_alias "${ALIAS}" 2> /dev/null)" ||: + if [ -n "${DEST}" ]; then + NVM_NO_COLORS="${NVM_NO_COLORS-}" NVM_LTS="${NVM_LTS-}" DEFAULT=false nvm_print_formatted_alias "${ALIAS}" "${DEST}" + fi +} + + +#SH.MET.RatioComment = 16.67 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=15 +#SH.MET.ComplexitySimplified = 3; +nvm_make_alias() { + local ALIAS + ALIAS="${1-}" + if [ -z "${ALIAS}" ]; then + nvm_err "an alias name is required" + return 1 + fi + local VERSION + VERSION="${2-}" + if [ -z "${VERSION}" ]; then + nvm_err "an alias target version is required" + return 2 + fi + nvm_echo "${VERSION}" | tee "$(nvm_alias_path)/${ALIAS}" >/dev/null +} + +#SH.MET.RatioComment = 16.67 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=15 +#SH.MET.ComplexitySimplified = 3; +nvm_alias() { + local ALIAS + ALIAS="${1-}" + if [ -z "${ALIAS}" ]; then + nvm_err 'An alias is required.' + return 1 + fi + + local NVM_ALIAS_PATH + NVM_ALIAS_PATH="$(nvm_alias_path)/${ALIAS}" + if [ ! -f "${NVM_ALIAS_PATH}" ]; then + nvm_err 'Alias does not exist.' + return 2 + fi + + command cat "${NVM_ALIAS_PATH}" +} + +#SH.MET.RatioComment = 14.29 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=18 +#SH.MET.ComplexitySimplified = 7; +nvm_ls_current() { + local NVM_LS_CURRENT_NODE_PATH + if ! NVM_LS_CURRENT_NODE_PATH="$(command which node 2> /dev/null)"; then + nvm_echo 'none' + elif nvm_tree_contains_path "$(nvm_version_dir iojs)" "${NVM_LS_CURRENT_NODE_PATH}"; then + nvm_add_iojs_prefix "$(iojs --version 2>/dev/null)" + elif nvm_tree_contains_path "${NVM_DIR}" "${NVM_LS_CURRENT_NODE_PATH}"; then + local VERSION + VERSION="$(node --version 2>/dev/null)" + if [ "${VERSION}" = "v0.6.21-pre" ]; then + nvm_echo 'v0.6.21' + else + nvm_echo "${VERSION}" + fi + else + nvm_echo 'system' + fi +} + +#SH.MET.RatioComment = 5.77 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=49 +#SH.MET.ComplexitySimplified = 11; +nvm_resolve_alias() { + if [ -z "${1-}" ]; then + return 1 + fi + + local PATTERN + PATTERN="${1-}" + + local ALIAS + ALIAS="${PATTERN}" + local ALIAS_TEMP + + local SEEN_ALIASES + SEEN_ALIASES="${ALIAS}" + while true; do + ALIAS_TEMP="$(nvm_alias "${ALIAS}" 2> /dev/null || echo)" + + if [ -z "${ALIAS_TEMP}" ]; then + break + fi + + if command printf "${SEEN_ALIASES}" | nvm_grep -e "^${ALIAS_TEMP}$" > /dev/null; then + ALIAS="∞" + break + fi + + SEEN_ALIASES="${SEEN_ALIASES}\n${ALIAS_TEMP}" + ALIAS="${ALIAS_TEMP}" + done + + if [ -n "${ALIAS}" ] && [ "_${ALIAS}" != "_${PATTERN}" ]; then + local NVM_IOJS_PREFIX + NVM_IOJS_PREFIX="$(nvm_iojs_prefix)" + local NVM_NODE_PREFIX + NVM_NODE_PREFIX="$(nvm_node_prefix)" + case "${ALIAS}" in + '∞' | \ + "${NVM_IOJS_PREFIX}" | "${NVM_IOJS_PREFIX}-" | \ + "${NVM_NODE_PREFIX}" ) + nvm_echo "${ALIAS}" + ;; + *) + nvm_ensure_version_prefix "${ALIAS}" + ;; + esac + return 0 + fi + + if nvm_validate_implicit_alias "${PATTERN}" 2> /dev/null ; then + local IMPLICIT + IMPLICIT="$(nvm_print_implicit_alias local "${PATTERN}" 2> /dev/null)" + if [ -n "${IMPLICIT}" ]; then + nvm_ensure_version_prefix "${IMPLICIT}" + fi + fi + + return 2 +} + +#SH.MET.RatioComment = 19.05 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=17 +#SH.MET.ComplexitySimplified = 5; +nvm_resolve_local_alias() { + if [ -z "${1-}" ]; then + return 1 + fi + + local VERSION + local EXIT_CODE + VERSION="$(nvm_resolve_alias "${1-}")" + EXIT_CODE=$? + if [ -z "${VERSION}" ]; then + return $EXIT_CODE + fi + if [ "_${VERSION}" != '_∞' ]; then + nvm_version "${VERSION}" + else + nvm_echo "${VERSION}" + fi +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_iojs_prefix() { + nvm_echo 'iojs' +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_node_prefix() { + nvm_echo 'node' +} + +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 2; +nvm_is_iojs_version() { + case "${1-}" in iojs-*) return 0 ;; esac + return 1 +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_add_iojs_prefix() { + nvm_echo "$(nvm_iojs_prefix)-$(nvm_ensure_version_prefix "$(nvm_strip_iojs_prefix "${1-}")")" +} + +#SH.MET.RatioComment = 29.411 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=9 +#SH.MET.ComplexitySimplified = 3; +nvm_strip_iojs_prefix() { + local NVM_IOJS_PREFIX + NVM_IOJS_PREFIX="$(nvm_iojs_prefix)" + if [ "${1-}" = "${NVM_IOJS_PREFIX}" ]; then + nvm_echo + else + nvm_echo "${1#${NVM_IOJS_PREFIX}-}" + fi +} + + +#SH.MET.RatioComment = 29.41 +#SH.MET.Nesting=2 +#SH.MET.LineOfCode=12 +#SH.MET.ComplexitySimplified = 4; +vm_ls_remote() { + local PATTERN + PATTERN="${1-}" + if nvm_validate_implicit_alias "${PATTERN}" 2> /dev/null ; then + PATTERN="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote "$(nvm_print_implicit_alias remote "${PATTERN}")" | command tail -1 | command awk '{ print $1 }')" + elif [ -n "${PATTERN}" ]; then + PATTERN="$(nvm_ensure_version_prefix "${PATTERN}")" + else + PATTERN=".*" + fi + NVM_LTS="${NVM_LTS-}" nvm_ls_remote_index_tab node std "${PATTERN}" +} + +#SH.MET.RatioComment = NaN +#SH.MET.Nesting=1 +#SH.MET.LineOfCode=3 +#SH.MET.ComplexitySimplified = 1; +nvm_ls_remote_iojs() { + NVM_LTS="${NVM_LTS-}" nvm_ls_remote_index_tab iojs std "${1-}" +} + +#SH.MET.RatioComment = 3.7 +#SH.MET.Nesting=3 +#SH.MET.LineOfCode=102 +#SH.MET.ComplexitySimplified = 17; +# args flavor, type, version +nvm_ls_remote_index_tab() { + local LTS + LTS="${NVM_LTS-}" + if [ "$#" -lt 3 ]; then + nvm_err 'not enough arguments' + return 5 + fi + + local FLAVOR + FLAVOR="${1-}" + + local TYPE + TYPE="${2-}" + + local MIRROR + MIRROR="$(nvm_get_mirror "${FLAVOR}" "${TYPE}")" + if [ -z "${MIRROR}" ]; then + return 3 + fi + + local PREFIX + PREFIX='' + case "${FLAVOR}-${TYPE}" in + iojs-std) PREFIX="$(nvm_iojs_prefix)-" ;; + node-std) PREFIX='' ;; + iojs-*) + nvm_err 'unknown type of io.js release' + return 4 + ;; + *) + nvm_err 'unknown type of node.js release' + return 4 + ;; + esac + local SORT_COMMAND + SORT_COMMAND='command sort' + case "${FLAVOR}" in + node) SORT_COMMAND='command sort -t. -u -k 1.2,1n -k 2,2n -k 3,3n' ;; + esac + + local PATTERN + PATTERN="${3-}" + + local VERSIONS + if [ -n "${PATTERN}" ]; then + if [ "${FLAVOR}" = 'iojs' ]; then + PATTERN="$(nvm_ensure_version_prefix "$(nvm_strip_iojs_prefix "${PATTERN}")")" + else + PATTERN="$(nvm_ensure_version_prefix "${PATTERN}")" + fi + else + unset PATTERN + fi + + ZSH_HAS_SHWORDSPLIT_UNSET=1 + if nvm_has "setopt"; then + ZSH_HAS_SHWORDSPLIT_UNSET="$(set +e ; setopt | nvm_grep shwordsplit > /dev/null ; nvm_echo $?)" + setopt shwordsplit + fi + local VERSION_LIST + VERSION_LIST="$(nvm_download -L -s "${MIRROR}/index.tab" -o - \ + | command sed " + 1d; + s/^/${PREFIX}/; + " \ + )" + local LTS_ALIAS + local LTS_VERSION + command mkdir -p "$(nvm_alias_path)/lts" + nvm_echo "${VERSION_LIST}" \ + | command awk '{ + if ($10 ~ /^\-?$/) { next } + if ($10 && !a[tolower($10)]++) { + if (alias) { print alias, version } + alias_name = "lts/" tolower($10) + if (!alias) { print "lts/*", alias_name } + alias = alias_name + version = $1 + } + } + END { + if (alias) { + print alias, version + } + }' \ + | while read -r LTS_ALIAS_LINE; do + LTS_ALIAS="${LTS_ALIAS_LINE%% *}" + LTS_VERSION="${LTS_ALIAS_LINE#* }" + nvm_make_alias "$LTS_ALIAS" "$LTS_VERSION" >/dev/null 2>&1 + done + + VERSIONS="$(nvm_echo "${VERSION_LIST}" \ + | command awk -v pattern="${PATTERN-}" -v lts="${LTS-}" '{ + if (!$1) { next } + if (pattern && tolower($1) !~ tolower(pattern)) { next } + if (lts == "*" && $10 ~ /^\-?$/) { next } + if (lts && lts != "*" && tolower($10) !~ tolower(lts)) { next } + if ($10 !~ /^\-?$/) print $1, $10; else print $1 + }' \ + | nvm_grep -w "${PATTERN:-.*}" \ + | $SORT_COMMAND)" + if [ "$ZSH_HAS_SHWORDSPLIT_UNSET" -eq 1 ] && nvm_has "unsetopt"; then + unsetopt shwordsplit + fi + if [ -z "${VERSIONS}" ]; then + nvm_echo 'N/A' + return 3 + fi + nvm_echo "${VERSIONS}" +} + diff --git a/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/RatioComment/TestSHMETRatioComment.java b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/RatioComment/TestSHMETRatioComment.java index aaba3239..827713ed 100755 --- a/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/RatioComment/TestSHMETRatioComment.java +++ b/tests/fr.cnes.analysis.tools.shell.metrics.test/src/fr/cnes/analysis/tools/shell/metrics/MET/RatioComment/TestSHMETRatioComment.java @@ -62,7 +62,7 @@ public void testRunWithError() { } } if (fileValue == null) { - fail("Erreur : Aucun résultat sur le fichier trouvé."); + fail("Erreur : Aucun r�sultat sur le fichier trouv�."); } else { assertTrue(fileValue.getFile().getName().equals(fileName)); diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.shell.rules.test/META-INF/MANIFEST.MF index 2451753b..543b119b 100644 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/META-INF/MANIFEST.MF @@ -2,9 +2,9 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES SH Rules Bundle-SymbolicName: fr.cnes.analysis.tools.shell.rules.test -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Vendor: CNES -Fragment-Host: fr.cnes.analysis.tools.shell.rules;bundle-version="3.0.1" +Fragment-Host: fr.cnes.analysis.tools.shell.rules;bundle-version="3.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.mockito;bundle-version="1.8.4", org.hamcrest;bundle-version="1.1.0", diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/pom.xml b/tests/fr.cnes.analysis.tools.shell.rules.test/pom.xml index e60f9e61..8138981e 100644 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.shell.rules.test diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/TestCOMDATAInitialisation.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/TestCOMDATAInitialisation.java index 8ea696f8..9c047481 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/TestCOMDATAInitialisation.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/TestCOMDATAInitialisation.java @@ -35,8 +35,8 @@ public class TestCOMDATAInitialisation { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 9 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM" }; + public final static int[] LINES = { 9, 15, 20, 25, 27, 32, 37 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "function1", "MAIN PROGRAM", "function2", "function2", "function3", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMDATAInitialisation(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/error.sh index 4a64227b..2fa92aa3 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/error.sh @@ -5,5 +5,33 @@ echo "Fichier KO de TU" echo "------------------------------------------" x=1 -# la variable y n'est pas initiliaze +# the y variable is not initialized z=$x+$y + +function function1 () +{ + b = 2 + # the c variable is not initialized + a = $b+$c +} + +# main - the y variable is not initialized + +xx=$y + +function2 () +{ + # the b variable is not initialized + a = $b + # the y variable is not initialized + d = $y + + function function3 () + { + # the y variable is not initialized + e = $y + } +} + +# the y variable is not initialized +yy=$y diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/noError.sh index 218bc313..3e527bb7 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Initialisation/noError.sh @@ -6,4 +6,28 @@ echo "------------------------------------------" x=1 y=2 -z=$x+$y \ No newline at end of file +z=$x+$y + +function function1 () +{ + b = 2 + c = 3 + a = $b+$c +} + +# main +xx=y + +function2 () +{ + b = 2 + a = $b+$xx + function function3 () + { + e = $a + } + + +} + +yy=$xx \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/TestCOMDATAInvariant.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/TestCOMDATAInvariant.java index a123ab36..680affaa 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/TestCOMDATAInvariant.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/TestCOMDATAInvariant.java @@ -35,9 +35,8 @@ public class TestCOMDATAInvariant { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 9, 14, 21, 13, 27, 8, 9 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "fonction", "MAIN PROGRAM", "fonction2", - "MAIN PROGRAM", "MAIN PROGRAM" }; + public final static int[] LINES = { 9, 14, 21, 27, 13, 8, 9, 30}; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "fonction", "fonction2", "MAIN PROGRAM", "MAIN PROGRAM" , "MAIN PROGRAM", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMDATAInvariant(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/error.sh index cb18a28d..fe501c4f 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/error.sh @@ -25,4 +25,6 @@ function fonction () fonction2 () { typeset pos=3 -} \ No newline at end of file +} + +position2=5; diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/noError.sh index 83ad3ddd..43bc4f9e 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/Invariant/noError.sh @@ -29,3 +29,21 @@ fonction2 () { typeset -r pos=3 } + + +function fonction3 () +{ + position3=5 + local position4=10 + + function fonction4 () + { + position3+=$position4 + } + position4=5 +} + +awk 'BEGIN { FS = " "; StartType = 0; StartEnum = 0; typeName=""; }' + +for (( PREPAR_UNE_SEUL_FOIS=0;$PREPAR_UNE_SEUL_FOIS<3;PREPAR_UNE_SEUL_FOIS++)) ; do echo "prepare" ; done + diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/TestCOMDATALoopCondition.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/TestCOMDATALoopCondition.java index 53faadcd..ae0421ea 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/TestCOMDATALoopCondition.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/TestCOMDATALoopCondition.java @@ -35,8 +35,8 @@ public class TestCOMDATALoopCondition { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 25, 41 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM" }; + public final static int[] LINES = { 27, 44 }; + public final static String[] LOCATIONS = { "testFunction", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMDATALoopCondition(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/error.sh index cb65e4f5..8c2c77b0 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DATA/LoopCondition/error.sh @@ -6,6 +6,8 @@ echo "------------------------------------------" echo "Printing Numbers 1 through 10 (but not 3)." +function testFunction () +{ LIMIT=1 a=0 @@ -25,6 +27,7 @@ do LIMIT=$(($LIMIT+1)) fi done +} # Imbric loops to verify variables changes b=0 @@ -35,7 +38,7 @@ while [ $b -le "$LIMIT1" ] do b=$(($b+1)) echo "Iteration $b " - while [ $c -le "$LIMIT2" ] + until [ $c -le "$LIMIT2" ] do c=$(($c+1)) LIMIT2=$(($LIMIT2-1)) diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/TestCOMDESIGNActiveWait.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/TestCOMDESIGNActiveWait.java index cbecdf7d..4bc6c5bb 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/TestCOMDESIGNActiveWait.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/TestCOMDESIGNActiveWait.java @@ -35,8 +35,8 @@ public class TestCOMDESIGNActiveWait { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 9, 20 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM" }; + public final static int[] LINES = { 9, 21, 25 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "readNum", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMDESIGNActiveWait(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/error.sh index 833026a8..a40ab740 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/DESIGN/ActiveWait/error.sh @@ -15,7 +15,11 @@ do fi i=$(($i+1)) done +function readNum () +{ + echo "Insert one number" + read x + echo "You insert: $x" +} -echo "Insert one number" -read x -echo "You insert: $x" +sleep 1024 diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/TestCOMFLOWAbort.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/TestCOMFLOWAbort.java index 4b9fa3d5..1867baaa 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/TestCOMFLOWAbort.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/TestCOMFLOWAbort.java @@ -35,8 +35,8 @@ public class TestCOMFLOWAbort { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 13, 14 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM" }; + public final static int[] LINES = { 13, 14, 22, 25 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "testFunction" , "MAIN PROGRAM" }; public final AbstractChecker rule = new COMFLOWAbort(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/error.sh index f9fc020f..b22c727b 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Abort/error.sh @@ -16,3 +16,11 @@ fi # kill process directly in one line #ps -ef | grep "ruby" | awk '{print $2}' | xargs kill + +function testFunction() +{ + kill $PID +} + +killall -9 $PID + diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/TestCOMFLOWCaseSwitch.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/TestCOMFLOWCaseSwitch.java index 52cfd430..37123402 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/TestCOMFLOWCaseSwitch.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/TestCOMFLOWCaseSwitch.java @@ -35,8 +35,8 @@ public class TestCOMFLOWCaseSwitch { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 17 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM" }; + public final static int[] LINES = { 17, 33, 37, 52 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "caseFunction", "caseFunction", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMFLOWCaseSwitch(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/error.sh index 8c812002..fcb17f2f 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/CaseSwitch/error.sh @@ -9,9 +9,44 @@ echo "What do you prefer: beach or moutain" read res case "$res" in "beach") - echo "Let's go to surfing" + echo "Let's go surfing" ;; "mountain" ) - echo "Let's go to skiing" + echo "Let's go skiing" + ;; +esac + +caseFunction () +{ + print "1) sub menu" + print "2) nothing" + + while true; do + read SELECT + case $SELECT in + 1) print "a) option a" + print "b) option b" + while read SELECT2;do + case $SELECT2 in + "a") print "A selected";; + "b") print "B selected";; + esac + break 2 + done;; + 2) print "2 selected";; + esac + break + done +} + +# --- Extraction des valeurs des parametres +echo "What do you prefer: town or country" +read res +case "$res" in + "town") + echo "Let's go to the cinema" + ;; + "country" ) + echo "Let's go for a walk" ;; esac diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/TestCOMFLOWFileExistence.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/TestCOMFLOWFileExistence.java index 4ae5754c..1658636c 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/TestCOMFLOWFileExistence.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/TestCOMFLOWFileExistence.java @@ -35,9 +35,9 @@ public class TestCOMFLOWFileExistence { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 8, 9, 11, 13, 15, 17, 18, 18, 20, 23, 26, 28 }; + public final static int[] LINES = { 8, 9, 11, 13, 15, 17, 18, 18, 20, 24, 27, 29 }; public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", - "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", + "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "my-function", "MAIN PROGRAM", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMFLOWFileExistence(); diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/error.sh index 6d75df63..efe78910 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FileExistence/error.sh @@ -19,6 +19,7 @@ grep ^2 $fictle > l1.tmp date>$fichier +my-function () if [ -e ${TAPE_DEV_REP}/${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz ] ; then cat "${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz" | Execute_Commande_C_Retour -d "cat - > ${TAPE_DEV_REP}/${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz" fi diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/TestCOMFLOWFilePath.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/TestCOMFLOWFilePath.java index 6e69ac42..75644bbe 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/TestCOMFLOWFilePath.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/TestCOMFLOWFilePath.java @@ -35,8 +35,10 @@ public class TestCOMFLOWFilePath { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 7, 8 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM" }; + public final static int[] LINES = { 7, 8, 9, 11, 13, 15, 17, 18, 18, 20, 23, 24, 27, 29, 29}; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", + "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", + "my-function", "my-function", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM"}; public final AbstractChecker rule = new COMFLOWFilePath(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/error.sh index e307b2c9..e79b4018 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/error.sh @@ -4,10 +4,26 @@ echo "COM.FLOW.FILEPATH" echo "Fichier KO de test" echo "------------------------------------------" -fichier_texte=/tmp/fichier_temporaire_$$.txt -fichier_texte_new=/tmp/fichier_temporaire_$$_new.txt +fichier= "fichier.txt" +echo "coucou" > $fichier +date > $fichier -if [ -f $fichier_texte ] || [ -f $fichier_texte_new ]; then - rm -f $fichier_texte - rm -f $fichier_texte_new -fi +echo "test" > $dirbdtle/bd_objet/$n1/$n2/RCS.txt + +cat "${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz" | Execute_Commande_C_Retour -d "cat - > ${TAPE_DEV_REP}/${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz" + +echo "${nom_machine} ${nb_proc}" > "${elec_export}"/fcf/machines.txt + +wc -l l1.tmp | awk '{print $1}' | read nbobj +grep ^2 $fictle > l1.tmp + +date>$fichier + +my-function () + if [ -e ${TAPE_DEV_REP}/${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz ] ; then + cat "${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz" | Execute_Commande_C_Retour -d "cat - > ${TAPE_DEV_REP}/${DATE_EXE}_${TYPE_ACTION}_${NIVEAU_SAUVEGARDE}_${MACHINE_S}.tar.gz" + fi + +grep -v "P" $ficsynthese + +rm -f /tmp/results.$$ /tmp/results.end.$$ 2>/dev/null diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/noError.sh index b8bce307..10b5ed14 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/FilePath/noError.sh @@ -4,7 +4,7 @@ echo "COM.FLOW.FilePath" echo "Fichier OK de test" echo "------------------------------------------" -if [ -f $fichier_texte ] || [ -f $fichier_texte_new ]; then - rm -f $fichier_texte - rm -f $fichier_texte_new +if [[ -n $REP_FICH_CONF ]]; then + echo "Le répertoire contenant le fichier de configuration est : + $REP_FICH_CONF" fi diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/TestCOMFLOWRecursion.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/TestCOMFLOWRecursion.java index e3887d25..ad7c1c49 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/TestCOMFLOWRecursion.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/TestCOMFLOWRecursion.java @@ -35,8 +35,8 @@ public class TestCOMFLOWRecursion { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 16, 38 }; - public final static String[] LOCATIONS = { "recursive_directe", "recursive_indirecte3" }; + public final static int[] LINES = { 16, 40, 48, 49 }; + public final static String[] LOCATIONS = { "recursive_directe", "recursive_indirecte2" , "recursive_indirecte3" , "recursive_indirecte3" }; public final AbstractChecker rule = new COMFLOWRecursion(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/error.sh index 0f52f348..ce8dd068 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/FLOW/Recursion/error.sh @@ -1,42 +1,53 @@ -#!/bin/bash -echo "------------------------------------------" -echo "COM.FLOW.RECURSION" -echo "Fichier KO de TU" -echo "------------------------------------------" - -recursive_directe() -{ - echo "Insert num between 1 to 10: magic num=5" - read num - if [ $num -eq 5 ] - then - echo "Bingo!" - else - echo "Try again" - recursive_directe - fi -} - -function recursive_indirecte1() -{ - echo "Insert num between 1 to 10: magin num=1" - recursive_indirecte2 -} -function recursive_indirecte2() -{ - read num - if [ $num -eq 1 ] - then - echo "Bingo!" - else - recursive_indirecte3 - fi -} -function recursive_indirecte3() -{ - echo "Try again" - recursive_indirecte1 -} - -recursive_directe -recursive_indirecte1 +#!/bin/bash +echo "------------------------------------------" +echo "COM.FLOW.RECURSION" +echo "Fichier KO de TU" +echo "------------------------------------------" + +recursive_directe() +{ + echo "Insert num between 1 to 10: magic num=5" + read num + if [ $num -eq 5 ] + then + echo "Bingo!" + else + echo "Try again" + recursive_directe + fi +} + +function recursive_indirecte1() +{ + echo "Insert num between 1 to 10: magin num=1" + recursive_indirecte2 +} +function recursive_indirecte2() +{ + recursive_indirecte4() + { + recursive_indirecte1 + } + read num + if [ $num -eq 1 ] + then + echo "Bingo!" + else + if [$num -eq 2] + then + recursive_indirecte3 + else + recursive_indirecte4 + fi + fi + +} +function recursive_indirecte3() +{ + echo "Try again" + recursive_indirecte1 + recursive_indirecte2 +} + +recursive_directe +recursive_indirecte1 diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/TestCOMINSTBoolNegation.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/TestCOMINSTBoolNegation.java index e2bba85a..fba7de74 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/TestCOMINSTBoolNegation.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/TestCOMINSTBoolNegation.java @@ -37,7 +37,7 @@ public class TestCOMINSTBoolNegation { public final static String NO_ERROR_FILE = "noError.sh"; public final static int[] LINES = { 9, 13, 17, 22, 27, 33, 40, 46 }; public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", - "MAIN PROGRAM", "test1", "test", "test" }; + "MAIN PROGRAM", "test1", "test", "MAIN PROGRAM" }; public final AbstractChecker rule = new COMINSTBoolNegation(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/noError.sh index 7e1414b7..046ea52d 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/INST/BoolNegation/noError.sh @@ -10,4 +10,9 @@ if [ ! $a -eq 0 ] && [ ! $a -eq 1 ] ; then echo "You entered a different number from 0 or 1" fi +if [ ! -r "$1" -o ! -f "$1" ] ; then + echo "This should be ok" +fi +debug ${!F}_${!L} "----------------> BEGIN: existsAndNotEmpty $item" +debug ${!F}_${!L} $(ls ${reportsDir}) diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/TestCOMNAMEHomonymy.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/TestCOMNAMEHomonymy.java index 85cc5700..e5e54a76 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/TestCOMNAMEHomonymy.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/TestCOMNAMEHomonymy.java @@ -35,9 +35,9 @@ public class TestCOMNAMEHomonymy { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 19, 27, 32, 41, 43, 51, 54, 60, 67, 69, 77 }; + public final static int[] LINES = { 19, 27, 32, 41, 43, 51, 54, 60, 67, 69, 78, 79 }; public final static String[] LOCATIONS = { "fonction_globale", "MAIN PROGRAM", "MAIN PROGRAM", "test2", "test2", - "test3", "test3", "test4", "test4", "test4", "test5" }; + "test3", "test3", "test4", "test4", "test4", "test5", "test5"}; public final AbstractChecker rule = new COMNAMEHomonymy(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/error.sh index 33cea986..cf8dde7d 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/error.sh @@ -70,9 +70,11 @@ while [ $a -eq 1 ] ; do fi set var=val #tcsh +_dir="test" function test5() { - # erreur -> variable locale avec le meme nom que la variable tcsh + # erreur -> variable locale avec le meme nom que la variable tcsh local var=5 + local _dir="fonction_test5" } \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/noError.sh index 123cfbf9..53c596f5 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/NAME/Homonymy/noError.sh @@ -4,12 +4,19 @@ echo "- COM.NAME.Homonymy -" echo "--------------------------" index=0 +_dir="test" +c=1 fonction () { local position_local=5 echo "Variable locale 'position' dans la fonction : $position_local" - + position_local=6 + index_=3 + local test_var="test" + echo $test_var + local _c=5 + _dir="test_fonction" echo "Variable globale 'index' dans la fonction : $index" } diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/TestCOMPRESIndent.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/TestCOMPRESIndent.java index f5d3a517..cca116ca 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/TestCOMPRESIndent.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/TestCOMPRESIndent.java @@ -35,10 +35,10 @@ public class TestCOMPRESIndent { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 18, 26, 45, 49, 59, 60, 64, 70, 78, 79 }; + public final static int[] LINES = { 18, 26, 45, 49, 59, 60, 64, 70, 78, 79, 92, 93, 94 }; public final static String[] LOCATIONS = { "ma_fonction_affine", "ma_fonction_affine", "affiche_resultat", - "affiche_resultat", "affiche_resultat", "affiche_resultat", "affiche_resultat", "affiche_resultat", - "affiche_resultat", "affiche_resultat" }; + "affiche_resultat", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", + "MAIN PROGRAM", "MAIN PROGRAM", "ma_fonction_affine2", "ma_fonction_affine2", "ma_fonction_affine2" }; public final AbstractChecker rule = new COMPRESIndent(); /** @@ -76,8 +76,8 @@ public void testRunWithError() { for (final CheckResult value : list) { final Integer index = list.indexOf(value); final String location = value.getLocation(); - assertTrue("CheckResult " + index.toString() + " has wrong location : " + location + " should contain " - + LOCATIONS[index], location.contains(LOCATIONS[index])); + assertTrue("CheckResult " + index.toString() + " has wrong location : " + location + " should be " + + LOCATIONS[index], location.equals(LOCATIONS[index])); final int line = value.getLine(); assertEquals("CheckResult " + index.toString() + " is in wrong line : ", LINES[index], line); } diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/error.sh index 8d714f43..1ce7d046 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/error.sh @@ -28,11 +28,11 @@ ma_fonction_affine () } + # ------------------------------------------------------------------------------------ # Definition d'une fonction qui affiche les resultats obtenus # ------------------------------------------------------------------------------------ -affiche_resultat () -{ +affiche_resultat () if [ $# -ne 2 ] then printf "Erreur grave dans affiche_resultat : nombre d'arguments incorrects\n" @@ -47,7 +47,7 @@ affiche_resultat () printf " ===>Erreur grave dans ma_fonction_affine : nombre d'arguments incorrects<===\n" fi fi -} + a_trouver=$(($RANDOM % 100)) @@ -79,4 +79,18 @@ else nbTarGbin=$(tar tvf ${FILETYPE}_${param: -4}.tar | grep gbin | wc -l) fi fi -fi \ No newline at end of file +fi + +function ma_fonction_affine2 () +{ + if [ $# -ne 3 ] + then + my_function=$code_error_nbargs + else + printf "Calling : p1=%s p2=%s p3=%s\n" $1 $2 $3 + # operation : y = ax + b + let y=$1*$2+$3 + printf "y=%s\n" $y + my_function=$y + fi +} diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/noError.sh index 106453b0..b6d2e6c4 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/noError.sh @@ -5,6 +5,8 @@ echo "Fichier OK de TU" echo "La indentation du code source est bonne" echo "------------------------------------------" +[[ $? != 0 ]] && { echo >&2 the required \"message\" command is not in your PATH; exit 1; } + code_erreur_nbargs=-128 # Définition de la variable qui contiendra le code retour (en particulier pour les cas d'erreur avec valeurs negatives) @@ -55,7 +57,6 @@ ma_fonction_affine () # Definition d'une fonction qui affiche les resultats obtenus # ------------------------------------------------------------------------------------ affiche_resultat () -{ if [ $# -ne 2 ] then printf "Erreur grave dans affiche_resultat : nombre d'arguments incorrects\n" @@ -70,7 +71,6 @@ affiche_resultat () printf " ===>Erreur grave dans ma_fonction_affine : nombre d'arguments incorrects<===\n" fi fi -} a_trouver=$(($RANDOM % 100)) @@ -87,3 +87,134 @@ do done echo "bravo, le nombre etait en effet $a_trouver" +# - Traitement du fichier des mouvements, impression de chaque +# - mouvement avec son type et calcul du solde bancaire +cat mvts.txt | awk 'BEGIN { print "Start AWK command" } + /^A/ {print "A---", NR } + /^B/ {print "B---", NR } + /^C/ {print "C---", NR } + /^D/ {print "D---", NR } + /^E/ {print "E---", NR } + /^F/ {print "F---", NR } + /^![A-F]/ {print "Default---", NR } + END { print "End AWK command" }' + +echo +echo "String operations using \"expr \$string : \" construct" +echo "===================================================" +echo + +a=1234zipper5FLIPPER43231 + +echo "The string being operated upon is \"`expr "$a" : '\(.*\)'`\"." +# Escaped parentheses grouping operator. == == + +# *************************** +#+ Escaped parentheses +#+ match a substring +# *************************** + + +# If no escaped parentheses... +#+ then 'expr' converts the string operand to an integer. + +echo "Length of \"$a\" is `expr "$a" : '.*'`." # Length of string + +echo "Number of digits at the beginning of \"$a\" is `expr "$a" : '[0-9]*'`." + +# ------------------------------------------------------------------------- # + +echo + +echo "The digits at the beginning of \"$a\" are `expr "$a" : '\([0-9]*\)'`." +# == == +echo "The first 7 characters of \"$a\" are `expr "$a" : '\(.......\)'`." +# ===== == == +# Again, escaped parentheses force a substring match. +# +echo "The last 7 characters of \"$a\" are `expr "$a" : '.*\(.......\)'`." +# ==== end of string operator ^^ +# (actually means skip over one or more of any characters until specified +#+ substring) + +echo + + +INIT_TAB_AWK="" +# Parameter to initialize awk script. +count_case=0 +FILE_PARSE=$1 + +E_PARAMERR=65 + +usage() +{ + echo "Usage: letter-count.sh file letters" 2>&1 + # For example: ./letter-count2.sh filename.txt a b c + exit $E_PARAMERR # Not enough arguments passed to script. +} + +if [ ! -f "$1" ] ; then + echo "$1: No such file." 2>&1 + usage # Print usage message and exit. +fi + +if [ -z "$2" ] ; then + echo "$2: No letters specified." 2>&1 + usage +fi + +shift # Letters specified. +for letter in `echo $@` # For each one . . . +do + INIT_TAB_AWK="$INIT_TAB_AWK tab_search[${count_case}] = \"$letter\"; final_tab[${count_case}] = 0; " + # Pass as parameter to awk script below. + count_case=`expr $count_case + 1` +done + +# DEBUG: +# echo $INIT_TAB_AWK; + +cat $FILE_PARSE | +# Pipe the target file to the following awk script. + +# ---------------------------------------------------------------------------------- +# Earlier version of script used: +# awk -v tab_search=0 -v final_tab=0 -v tab=0 -v nb_letter=0 -v chara=0 -v chara2=0 \ + +awk \ +"BEGIN { $INIT_TAB_AWK } \ +{ split(\$0, tab, \"\"); \ +for (chara in tab) \ +{ for (chara2 in tab_search) \ +{ if (tab_search[chara2] == tab[chara]) { final_tab[chara2]++ } } } } \ +END { for (chara in final_tab) \ +{ print tab_search[chara] \" => \" final_tab[chara] } }" +# ---------------------------------------------------------------------------------- +# Nothing all that complicated, just . . . +#+ for-loops, if-tests, and a couple of specialized functions. + + +# ----------------------------------------------------------------------- +# Every file has an inode, a record that holds its physical address info. +# ----------------------------------------------------------------------- + +echo; echo -n "Are you absolutely sure you want to delete \"$1\" (y/n)? " +# The '-v' option to 'rm' also asks this. +read answer +case "$answer" in + [nN]) echo "Changed your mind, huh?" + exit $E_CHANGED_MIND + ;; + *) echo "Deleting file \"$1\".";; +esac + +awk ' +{nodecount()} # Execute the user-defined nodecount() for each row to update the node count +$0~//{ print } # Print the rows between "" +function nodecount() #Function definition for nodecount +{if($0~/clusternode name/){count+=1} +} +END{print "Node Count="count}' $1 #Print the count value in the END pattern which is executed once + + diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/test.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/test.sh index faf42186..c2b0395d 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/test.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/Indent/test.sh @@ -1,45 +1,43 @@ -#!/bin/sh - - -while getopts "p:hs:" arg;do -case $arg in -p) if test $# -eq 3 && [[ "$2" =~ [2][0][1-2][0-9][0-1][0-9][0-3][0-9] ]] && [[ "$3" =~ [2][0][1-2][0-9][0-1][0-9][0-3][0-9] ]] ; then - - START=$(date -d ${2:0:4}-${2:4:2}-${2:6:2} "+%y%m%d") - STOP=$(date -d ${3:0:4}-${3:4:2}-${3:6:2} "+%y%m%d") - typeset -i nbDays=0 - if [ $STOP -ge $START ] - then - while (( $STOP >= $START )) - do - tabDate[$nbDays]=$(date +%Y%m%d -d "$START") #built table containing every day between Start and Stop Date - let nbDays++ #table compteur +1 - START=$(date +%y%m%d -d "$START + 1 day") #Day +1 - done - tarList ${tabDate[@]} # Send builted table with date to tarList function as argument - fi - else - echo -e "Error--Wrong usage, please check usage (-h)\n" - fi - exit;; -s)echo "Not coded yet" -exit;; -:)echo "Error--Option -$OPTARG need arguments " ; exit ;; -h)display_usage -exit;; -/?)exit;; -esac -done - -case $1 in - -[2][0][1-2][0-9][0-1][0-9][0-3][0-9] ) for parameters in "$@" - do - if ! [[ "$parameters" =~ [2][0][1-2][0-9][0-1][0-9][0-3][0-9] ]]; then - echo -e "ERROR--Wrong format, please check usage (-h)\n" - exit - fi - done - tarList "$@";; -*) echo -e "ERROR--Wrong entry, please check usage (-h)\n";; +#!/bin/sh +while getopts "p:hs:" arg;do +case $arg in +p) if test $# -eq 3 && [[ "$2" =~ [2][0][1-2][0-9][0-1][0-9][0-3][0-9] ]] && [[ "$3" =~ [2][0][1-2][0-9][0-1][0-9][0-3][0-9] ]] ; then + + START=$(date -d ${2:0:4}-${2:4:2}-${2:6:2} "+%y%m%d") + STOP=$(date -d ${3:0:4}-${3:4:2}-${3:6:2} "+%y%m%d") + typeset -i nbDays=0 + if [ $STOP -ge $START ] + then + while (( $STOP >= $START )) + do + tabDate[$nbDays]=$(date +%Y%m%d -d "$START") #built table containing every day between Start and Stop Date + let nbDays++ #table compteur +1 + START=$(date +%y%m%d -d "$START + 1 day") #Day +1 + done + tarList ${tabDate[@]} # Send builted table with date to tarList function as argument + fi + else + echo -e "Error--Wrong usage, please check usage (-h)\n" + fi + exit;; +s)echo "Not coded yet" +exit;; +:)echo "Error--Option -$OPTARG need arguments " ; exit ;; +h)display_usage +exit;; +/?)exit;; +esac +done + +case $1 in + +[2][0][1-2][0-9][0-1][0-9][0-3][0-9] ) for parameters in "$@" + do + if ! [[ "$parameters" =~ [2][0][1-2][0-9][0-1][0-9][0-3][0-9] ]]; then + echo -e "ERROR--Wrong format, please check usage (-h)\n" + exit + fi + done + tarList "$@";; +*) echo -e "ERROR--Wrong entry, please check usage (-h)\n";; esac \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/TestCOMPRESLengthLine.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/TestCOMPRESLengthLine.java index e0994ba2..dc874937 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/TestCOMPRESLengthLine.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/TestCOMPRESLengthLine.java @@ -35,8 +35,8 @@ public class TestCOMPRESLengthLine { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 9, 45, 47 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "affiche_resultat", "affiche_resultat" }; + public final static int[] LINES = { 9, 18, 48, 55, 57, 75}; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "ma_fonction_affine", "affiche_resultat", "test_length", "affiche_resultat", "MAIN PROGRAM"}; public final AbstractChecker rule = new COMPRESLengthLine(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/error.sh index 3f94d936..943a1092 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/COM/PRES/LengthLine/error.sh @@ -6,7 +6,7 @@ echo "------------------------------------------" code_erreur_nbargs=-128 -# Dénition de la variable qui contiendra le code retour (en particulier pour les cas d'erreur avec valeurs negatives) +# Dénition de la variable qui contiendra le code retour (en particulier pour les cas d'erreur avec valeurs negatives) - function test r_ma_fonction_affine= # ------------------------------------------------------------------------------------ @@ -14,13 +14,14 @@ r_ma_fonction_affine= # ------------------------------------------------------------------------------------ ma_fonction_affine () { - if [ $# -ne 3 ] + + printf "This is a long line in the ma_fonction_affine function to test the line length maximum" + + if [ $# -ne 3 ] then r_ma_fonction_affine=$code_erreur_nbargs else -# printf "interface appel fonction ok : p1=%s p2=%s p3=%s\n" $1 $2 $3 - # calcul : y = ax + b let y=$1*$2+$3 # printf "y=%s\n" $y @@ -36,18 +37,25 @@ affiche_resultat () { if [ $# -ne 2 ] then - printf "Erreur grave dans affiche_resultat : nombre d'arguments incorrects\n" + printf "Erreur grave dans affiche_resultat : nombre d'arguments incorrects" else p1=$1 p2=$2 if [ $p2 -ge 0 ] then - printf "execution de 'ma_fonction_affine' avec chaine de calcul : %s resultat = %s \n" $p1 $2 + printf "execution de 'ma_fonction_affine' avec chaine de calcul : %s resultat = %s " $p1 $2 else - printf "erreur d'execution de 'ma_fonction_affine' avec chaine de calcul : %s code retour = %s\n" $p1 $p2 - printf " ===>Erreur grave dans ma_fonction_affine : nombre d'arguments incorrects<===\n" + printf "erreur d'execution de 'ma_fonction_affine' avec chaine de calcul : %s code retour = %s" $p1 $p2 + printf " ===>Erreur grave dans ma_fonction_affine : nombre d'arguments incorrects<===" fi fi + + function test_length () + { + printf "this too is a very very very very very very very very very very long line to test the length limit pb anti-n\n" + } + printf "this too is a very very very very long line to test the length limit while out of the included function pb anti-n\n" + } a_trouver=$(($RANDOM % 100)) @@ -64,6 +72,6 @@ do fi read i done -echo "bravo, le nombre etait en effet $a_trouver" +echo "bravo, le nombre etait en effet $a_trouver, vous avez gagne !!!!! Merci de relancer si vous voulez rejouer" diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckArguments/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckArguments/noError.sh index c2d822a1..446e0eab 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckArguments/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckArguments/noError.sh @@ -15,6 +15,18 @@ ma_fonction_affine () r_ma_fonction_affine=$y fi } +ma_fonction_affine2 () +{ + if [ ${#} -ne 3 ] + then + r_ma_fonction_affine=$code_erreur_nbargs + echo "WARNING !!! ma fonction ma_fonction_affine() a été lancée !" + else + # calcul : y = ax + b + let y=$1*$2+$3 + r_ma_fonction_affine=$y + fi +} typeset -i a=3 typeset -i x=12 @@ -25,3 +37,6 @@ ma_fonction_affine $a $x $b # --- Appel de la fonction avec 2 parametres ma_fonction_affine $a $x + +# --- Appel de la fonction avec 2 parametres +ma_fonction_affine2 $a $x $b diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/TestSHFLOWCheckCodeReturn.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/TestSHFLOWCheckCodeReturn.java index 4aaad1ac..02e25435 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/TestSHFLOWCheckCodeReturn.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/TestSHFLOWCheckCodeReturn.java @@ -35,9 +35,9 @@ public class TestSHFLOWCheckCodeReturn { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 29, 32, 34, 35, 40, 44, 46 }; - public final static String[] LOCATIONS = { "factorial", "factorial", "factorial", "factorial", - "nettoyer_repertoire", "nettoyer_repertoire", "nettoyer_repertoire" }; + public final static int[] LINES = { 29, 32, 34, 35, 40, 44, 46, 48}; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", + "nettoyer_repertoire", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM" }; public final AbstractChecker rule = new SHFLOWCheckCodeReturn(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/error.sh index a49eff3b..cb0f1014 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/error.sh @@ -45,3 +45,4 @@ date +%d_%m_%y | sed -e 's,_, ,g' | awk '{print $1,$2,$3+2000}' | read jj mm aaa nettoyer_repertoire "${tmpdir}" +grep "Date :" $ficresarc | awk '{print $3}' > datejul.tmp \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/noError.sh index 7f42edcb..7c2310ea 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/FLOW/CheckCodeReturn/noError.sh @@ -45,4 +45,23 @@ else fi date +%d_%m_%y | sed -e 's,_, ,g' | awk '{print $1,$2,$3+2000}' | read jj mm aaaa -retour=$? \ No newline at end of file +retour=$? + +cd -- "$idir" || { echo >&2 can not cd to "$idir"; exit 1; } + +funcname () +{ + echo "hello" +} + +export –f funcName + +cd -- "$idir" +case $? in + 0) echo -n "0";; + *) echo -n "cd error";; +esac + +right_now=$(date +"%x %r %Z") +# limitation: $() commands are not tested +files=$(ls) \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/TestSHIORedirect.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/TestSHIORedirect.java index 19aa95e4..5b1e573b 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/TestSHIORedirect.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/TestSHIORedirect.java @@ -36,8 +36,8 @@ public class TestSHIORedirect { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 13, 14, 17, 18, 19 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", + public final static int[] LINES = { 13, 14, 17, 21, 24 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "MAIN PROGRAM", "MAIN PROGRAM", "my-function", "MAIN PROGRAM" }; public final AbstractChecker rule = new SHIORedirect(); @@ -64,8 +64,6 @@ public void testRunWithError() { // We verify that there is the right number of errors final int nb_CheckResults = list.size(); - for (CheckResult v : list) - System.out.println(v.getLine()); assertEquals("Wrong number of CheckResults : ", LINES.length, nb_CheckResults); // We verify that the error detected is the right one. There is diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/error.sh index 796f27b3..68c7ed19 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/IO/Redirect/error.sh @@ -15,5 +15,10 @@ res=`ls -l 2>&1` dd if=$randomizer of=$output_file bs=$block_size count=3 dd_stats='^[0-9]+\+[0-9]+ records (in|out)$' res=`((dd if=$output_file ibs=$block_size 2>&1 1>&3 3>&- 4>&-; -echo $?>&4 + +my-function () +{ + echo $?>&4 +} + egrep -v "$dd_stats" 1>&2 3>&- 4>&-) 4>&1` \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/TestSHMETPipeLine.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/TestSHMETPipeLine.java index e1f33f17..63edccc3 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/TestSHMETPipeLine.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/TestSHMETPipeLine.java @@ -35,8 +35,8 @@ public class TestSHMETPipeLine { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 8 }; - public final static String[] LOCATIONS = { "MAIN PROGRAM" }; + public final static int[] LINES = { 8, 16, 19 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "test1", "test" }; public final AbstractChecker rule = new SHMETPipeLine(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/error.sh index c2915d0f..4cdc3b90 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/error.sh @@ -6,4 +6,15 @@ echo "--------------------" ls -l | sed -e "s/[eiou]/a/g" - + +compress=1 + +function test () +{ + test1 () + if [$compress]; then + tar tvf ./archive.tar | awk '{print $3, $6}' | egrep '\.c$' | sort -nr | head -1 + fi + test1 + ls -l | sed -e "s/[eiou]/a/g" +} \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/noError.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/noError.sh index 8053b48d..c57401c6 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/noError.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/MET/PipeLine/noError.sh @@ -8,3 +8,36 @@ echo "--------------------" # et fait la substituition de les vocals [aeio] pas [u] ls -l | sed -e "s/[aeio]/u/g" + +function test () +{ + test1 () + if [$compress]; then + # this is a comment for the pipe command + tar tvf ./archive.tar | awk '{print $3, $6}' | egrep '\.c$' | sort -nr | head -1 + fi + test1 + # another comment + + ls -l | sed -e "s/[eiou]/a/g" +} +# Cette commande permet de recherche dans un archive tous les +# fichier d’extension « .c » et d’afficher le plus volumineux +tar tvf ./archive.tar | awk '{print $3, $6}' | egrep '\.c$' | sort -nr | head -1 + +case ${OPTARG} in + help ) input_to_process=0; + usage;; + version ) input_to_process=0; + echo "ql_s2 V1.6 using OTB 6.6";; + sd=?* ) destination_sub_directory=${LONG_OPTARG};; + sd* ) echo "No arg for --${OPTARG} option" >&2; + exit 1;; + rgb | irgb | comp ) quicklook_type=${OPTARG};; + rgb* | irgb* | comp* ) + echo "No arg allowed for --${OPTARG} option" >&2; + exit 1;; + '') break ;; # "--" terminates argument processing + *) echo "No arg allowed for --${OPTARG} option" >&2; + exit 1;; +esac \ No newline at end of file diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/TestSHREFExport.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/TestSHREFExport.java index 38b3980e..4703c3b9 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/TestSHREFExport.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/TestSHREFExport.java @@ -35,8 +35,8 @@ public class TestSHREFExport { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; - public final static int[] LINES = { 18 }; - public final static String[] LOCATIONS = { "verifie_seuil_shell" }; + public final static int[] LINES = { 18, 27, 30 }; + public final static String[] LOCATIONS = { "MAIN PROGRAM", "testFunction","MAIN PROGRAM" }; public final AbstractChecker rule = new SHREFExport(); /** diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/error.sh b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/error.sh index fd419e20..d0376451 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/error.sh +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/REF/Export/error.sh @@ -14,10 +14,17 @@ verifie_seuil_shell() # --- Export d'une constante typeset -r MAX_SHELL_LEVEL=2 export MAX_SHELL_LEVEL -# --- Export d'une certaine fonctions +# --- Export d'une certaine function export -f verifie_seuil_shell # --- Variables locales nom_script=$(basename $0) echo "Variable exportee au $nom_script s'appelle MAX_SHELL_LEVEL" -echo "Founction exportee au $nom_script s'appelle verifie_seuil_shell" \ No newline at end of file +echo "function exportee au $nom_script s'appelle verifie_seuil_shell" + +function testFunction () +{ + export -f verifie_seuil_shell +} + +export -f testFunction diff --git a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/SYNC/Signals/TestSHSYNCSignals.java b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/SYNC/Signals/TestSHSYNCSignals.java index 8e32f649..74824d30 100755 --- a/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/SYNC/Signals/TestSHSYNCSignals.java +++ b/tests/fr.cnes.analysis.tools.shell.rules.test/src/fr/cnes/analysis/tools/shell/rules/SH/SYNC/Signals/TestSHSYNCSignals.java @@ -36,7 +36,7 @@ public class TestSHSYNCSignals { public final static String ERROR_FILE = "error.sh"; public final static String NO_ERROR_FILE = "noError.sh"; public final static int[] LINES = { 57 }; - public final static String[] LOCATIONS = { "nettoie" }; + public final static String[] LOCATIONS = { "MAIN PROGRAM" }; public final AbstractChecker rule = new SHSYNCSignals(); /** diff --git a/tests/fr.cnes.analysis.tools.ui.test/META-INF/MANIFEST.MF b/tests/fr.cnes.analysis.tools.ui.test/META-INF/MANIFEST.MF index 0905575f..0d863049 100644 --- a/tests/fr.cnes.analysis.tools.ui.test/META-INF/MANIFEST.MF +++ b/tests/fr.cnes.analysis.tools.ui.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tests for i-Code CNES UI Bundle-SymbolicName: fr.cnes.analysis.tools.ui.test -Bundle-Version: 3.0.1.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Vendor: CNES Fragment-Host: fr.cnes.analysis.tools.ui;bundle-version="2.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/tests/fr.cnes.analysis.tools.ui.test/pom.xml b/tests/fr.cnes.analysis.tools.ui.test/pom.xml index 86bdc46a..93e25ab4 100644 --- a/tests/fr.cnes.analysis.tools.ui.test/pom.xml +++ b/tests/fr.cnes.analysis.tools.ui.test/pom.xml @@ -6,7 +6,7 @@ fr.cnes.icode fr.cnes.icode.test.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.analysis.tools.ui.test diff --git a/tests/pom.xml b/tests/pom.xml index c0226831..8be5c21b 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -7,7 +7,7 @@ fr.cnes.icode fr.cnes.icode.parent - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT fr.cnes.icode.test.parent