diff --git a/integration-tests/features/multimodule_analysis.feature b/integration-tests/features/multimodule_analysis.feature
index 9606a46670..ca7878d739 100644
--- a/integration-tests/features/multimodule_analysis.feature
+++ b/integration-tests/features/multimodule_analysis.feature
@@ -36,8 +36,8 @@ Feature: cpp-multimodule-project
| comment_lines_density | 30 |
| comment_lines | 24 |
# duplications
- | duplicated_lines_density | 57.3 |
- | duplicated_lines | 86 |
+ | duplicated_lines_density | 56.0 |
+ | duplicated_lines | 84 |
| duplicated_blocks | 2 |
| duplicated_files | 2 |
# complexity
diff --git a/integration-tests/features/smoketest.feature b/integration-tests/features/smoketest.feature
index d30f169227..def875b284 100644
--- a/integration-tests/features/smoketest.feature
+++ b/integration-tests/features/smoketest.feature
@@ -31,8 +31,8 @@ Feature: Smoketest
| comment_lines_density | 30 |
| comment_lines | 24 |
# duplications
- | duplicated_lines_density | 57.0 |
- | duplicated_lines | 86 |
+ | duplicated_lines_density | 55.6 |
+ | duplicated_lines | 84 |
| duplicated_blocks | 2 |
| duplicated_files | 2 |
# complexity
diff --git a/pom.xml b/pom.xml
index 86626d6923..4a5718accf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,12 @@
org.sonarsource.parent
parent
- 32
+
+ 36
org.sonarsource.sonarqube-plugins.cxx
@@ -165,7 +170,10 @@
http://github.com/SonarOpenCommunity/sonar-cxx
true
5.6
+
+ 1.17
1.21
+ 2.6.1
org.sonar.plugins.cxx.CxxPlugin
target/${project.artifactId}-${project.version}.jar
C++ (Community)
@@ -213,19 +221,27 @@
org.sonarsource.sslr-squid-bridge
sslr-squid-bridge
- 2.6.1
+ ${sslr-squid-bridge.version}
org.codehaus.sonar.sslr
sslr-core
+
+ org.codehaus.sonar.sslr
+ sslr-xpath
+
org.codehaus.sonar
sonar-plugin-api
- org.codehaus.sonar.sslr
- sslr-xpath
+ org.picocontainer
+ picocontainer
+
+
+ org.slf4j
+ slf4j-api
org.slf4j
@@ -257,7 +273,7 @@
org.slf4j
slf4j-api
- 1.6.2
+ 1.7.21
test
diff --git a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxCpdMapping.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxCpdMapping.java
deleted file mode 100644
index 270a8ebc61..0000000000
--- a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxCpdMapping.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Sonar C++ Plugin (Community)
- * Copyright (C) 2010-2016 SonarOpenCommunity
- * http://github.com/SonarOpenCommunity/sonar-cxx
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.cxx;
-
-import java.nio.charset.Charset;
-
-import net.sourceforge.pmd.cpd.Tokenizer; //@todo deprecated
-
-import org.sonar.api.batch.AbstractCpdMapping; //@todo deprecated
-import org.sonar.api.resources.Language;
-import org.sonar.api.batch.fs.FileSystem;
-
-public class CxxCpdMapping extends AbstractCpdMapping {
-
- private final CxxLanguage language;
- private final Charset charset;
-
- public CxxCpdMapping(CxxLanguage language, FileSystem fs) {
- this.language = language;
- this.charset = fs.encoding();
- }
-
- @Override
- public Tokenizer getTokenizer() { //@todo deprecated Tokenizer
- return new CxxTokenizer(charset);
- }
-
- @Override
- public Language getLanguage() {
- return language;
- }
-
-}
diff --git a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java
index 01f6ecb7dc..8086392a15 100644
--- a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java
+++ b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java
@@ -385,7 +385,6 @@ public void define(Context context) {
l.add(CxxLanguage.class);
l.add(CxxMetrics.class);
l.add(CxxSquidSensor.class);
- l.add(CxxCpdMapping.class);
l.add(CxxRatsRuleRepository.class);
l.add(CxxRatsSensor.class);
l.add(CxxXunitSensor.class);
diff --git a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxTokenizer.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxTokenizer.java
deleted file mode 100644
index 22eccda585..0000000000
--- a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxTokenizer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Sonar C++ Plugin (Community)
- * Copyright (C) 2010-2016 SonarOpenCommunity
- * http://github.com/SonarOpenCommunity/sonar-cxx
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.cxx;
-
-import java.io.File;
-import java.nio.charset.Charset;
-import java.util.List;
-
-import net.sourceforge.pmd.cpd.SourceCode; //@todo deprecated
-import net.sourceforge.pmd.cpd.TokenEntry; //@todo deprecated
-import net.sourceforge.pmd.cpd.Tokenizer; //@todo deprecated
-import net.sourceforge.pmd.cpd.Tokens; //@todo deprecated
-
-import org.sonar.cxx.CxxConfiguration;
-import org.sonar.cxx.lexer.CxxLexer;
-
-import com.sonar.sslr.api.Token;
-import com.sonar.sslr.impl.Lexer;
-
-public class CxxTokenizer implements Tokenizer {
-
- private final Charset charset;
-
- public CxxTokenizer(Charset charset) {
- this.charset = charset;
- }
-
- @Override
- public final void tokenize(SourceCode source, Tokens cpdTokens) { //@todo deprecated SourceCode
- Lexer lexer = CxxLexer.create(new CxxConfiguration(charset));
- String fileName = source.getFileName();
- List tokens = lexer.lex(new File(fileName));
- for (Token token : tokens) {
- TokenEntry cpdToken = new TokenEntry(getTokenImage(token), fileName, token.getLine());
- cpdTokens.add(cpdToken);
- }
- cpdTokens.add(TokenEntry.getEOF());
- }
-
- private String getTokenImage(Token token) {
- return token.getValue();
- }
-
-}
diff --git a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/cpd/CxxCpdVisitor.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/cpd/CxxCpdVisitor.java
new file mode 100644
index 0000000000..65407c44dd
--- /dev/null
+++ b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/cpd/CxxCpdVisitor.java
@@ -0,0 +1,83 @@
+/*
+ * Sonar C++ Plugin (Community)
+ * Copyright (C) 2010-2016 SonarOpenCommunity
+ * http://github.com/SonarOpenCommunity/sonar-cxx
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.plugins.cxx.cpd;
+
+import java.io.File;
+import javax.annotation.Nullable;
+
+import com.sonar.sslr.api.AstAndTokenVisitor;
+import com.sonar.sslr.api.AstNode;
+import com.sonar.sslr.api.GenericTokenType;
+import com.sonar.sslr.api.Grammar;
+import com.sonar.sslr.api.Token;
+import org.sonar.squidbridge.SquidAstVisitor;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.cxx.api.CxxTokenType;
+
+public class CxxCpdVisitor extends SquidAstVisitor implements AstAndTokenVisitor {
+
+ private final SensorContext sensorContext;
+ private InputFile inputFile;
+ private NewCpdTokens cpdTokens;
+
+ public CxxCpdVisitor(SensorContext sensorContext) {
+ this.sensorContext = sensorContext;
+ }
+
+ @Override
+ public void visitFile(@Nullable AstNode astNode) {
+ File file = getContext().getFile();
+ inputFile = sensorContext.fileSystem().inputFile(sensorContext.fileSystem().predicates().is(file));
+ cpdTokens = sensorContext.newCpdTokens().onFile(inputFile);
+ }
+
+ @Override
+ public void leaveFile(@Nullable AstNode astNode) {
+ cpdTokens.save();
+ }
+
+ @Override
+ public void visitToken(Token token) {
+ if (!token.isGeneratedCode()) {
+ String text;
+ if (token.getType().equals(CxxTokenType.NUMBER)) {
+ text = "_N";
+ } else if (token.getType().equals(CxxTokenType.STRING)) {
+ text = "_S";
+ } else if (token.getType().equals(CxxTokenType.CHARACTER)) {
+ text = "_C";
+ } else if (token.getType().equals(GenericTokenType.IDENTIFIER)) {
+ text = "_I";
+ } else if (token.getType().equals(GenericTokenType.EOF)) {
+ return;
+ } else {
+ text = token.getValue();
+ }
+
+ TextRange range = inputFile.newRange(token.getLine(), token.getColumn(), token.getLine(), token.getColumn() + token.getValue().length());
+ cpdTokens.addToken(range, text);
+ }
+ }
+
+}
diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxCpdMappingTest.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/cpd/package-info.java
similarity index 60%
rename from sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxCpdMappingTest.java
rename to sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/cpd/package-info.java
index 3c105f8b9e..8a4d46bc6d 100644
--- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxCpdMappingTest.java
+++ b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/cpd/package-info.java
@@ -17,22 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.plugins.cxx;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.FileSystem;
-
-public class CxxCpdMappingTest {
+/**
+ * Package with visitor to define tokens used by CPD algorithm on files.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.plugins.cxx.cpd;
- @Test
- public void testMapping() {
- CxxLanguage language = mock(CxxLanguage.class);
- FileSystem fs = TestUtils.mockFileSystem();
- CxxCpdMapping mapping = new CxxCpdMapping(language, fs);
- assertThat(mapping.getLanguage()).isSameAs(language);
- assertThat(mapping.getTokenizer()).isInstanceOf(CxxTokenizer.class);
- }
-}
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/squid/CxxSquidSensor.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/squid/CxxSquidSensor.java
index 13ee3b78d3..6b61628248 100644
--- a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/squid/CxxSquidSensor.java
+++ b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/squid/CxxSquidSensor.java
@@ -62,6 +62,7 @@
import org.sonar.api.ce.measure.RangeDistributionBuilder;
import org.sonar.api.rule.RuleKey;
import org.sonar.cxx.parser.CxxParser;
+import org.sonar.plugins.cxx.cpd.CxxCpdVisitor;
import org.sonar.plugins.cxx.highlighter.CxxHighlighter;
@@ -111,6 +112,7 @@ public void describe(SensorDescriptor descriptor) {
public void execute(SensorContext context) {
List> visitors = new ArrayList<>((Collection) checks.all());
visitors.add(new CxxHighlighter(context));
+ visitors.add(new CxxCpdVisitor(context));
this.scanner = CxxAstScanner.create(createConfiguration(context.fileSystem(), this.settings), context,
visitors.toArray(new SquidAstVisitor[visitors.size()]));
diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java
index 3867170c47..fa1850d88c 100644
--- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java
+++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java
@@ -32,6 +32,6 @@ public void testGetExtensions() throws Exception {
Plugin.Context context = new Plugin.Context(SonarQubeVersion.V5_6);
CxxPlugin plugin = new CxxPlugin();
plugin.define(context);
- assertThat(context.getExtensions()).hasSize(63);
+ assertThat(context.getExtensions()).hasSize(62);
}
}
diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxTokenizerTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxTokenizerTest.java
deleted file mode 100644
index 9a62d1e574..0000000000
--- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxTokenizerTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Sonar C++ Plugin (Community)
- * Copyright (C) 2010-2016 SonarOpenCommunity
- * http://github.com/SonarOpenCommunity/sonar-cxx
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.cxx;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-import java.io.File;
-import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-import java.util.List;
-
-import net.sourceforge.pmd.cpd.SourceCode; //@todo deprecated
-import net.sourceforge.pmd.cpd.TokenEntry; //@todo deprecated
-import net.sourceforge.pmd.cpd.Tokens; //@todo deprecated
-
-import org.junit.Test;
-
-public class CxxTokenizerTest {
-
- @Test
- public void shouldWorkOnValidInput() throws URISyntaxException {
- File file = new File(getClass().getResource("codechunks-project/code_chunks.cc").toURI());
- SourceCode source = new SourceCode(new SourceCode.FileCodeLoader(file, "key")); //@todo deprecated SourceCode
- Tokens cpdTokens = new Tokens(); //@todo deprecated Tokens
- CxxTokenizer tokenizer = new CxxTokenizer(Charset.forName("UTF-8"));
- tokenizer.tokenize(source, cpdTokens);
- List list = cpdTokens.getTokens(); //@todo deprecated TokenEntry
- assertThat(list.size()).isEqualTo(371);
- }
-
-}
diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/cpd/CxxCpdVisitorTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/cpd/CxxCpdVisitorTest.java
new file mode 100644
index 0000000000..7a32682fcb
--- /dev/null
+++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/cpd/CxxCpdVisitorTest.java
@@ -0,0 +1,86 @@
+/*
+ * Sonar C++ Plugin (Community)
+ * Copyright (C) 2010-2016 SonarOpenCommunity
+ * http://github.com/SonarOpenCommunity/sonar-cxx
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.plugins.cxx.cpd;
+
+import java.io.File;
+import java.util.List;
+import org.apache.commons.io.Charsets;
+import static org.fest.assertions.Assertions.assertThat;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
+import org.sonar.cxx.CxxAstScanner;
+
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.duplications.internal.pmd.TokensLine;
+
+public class CxxCpdVisitorTest {
+
+ private SensorContextTester context;
+ private DefaultInputFile inputFile;
+
+ @Before
+ @SuppressWarnings("unchecked")
+ public void scanFile() {
+ String dir = "src/test/resources/org/sonar/plugins/cxx";
+
+ File file = new File(dir, "/cpd.cc");
+ inputFile = new DefaultInputFile("moduleKey", file.getName())
+ .initMetadata(new FileMetadata().readMetadata(file, Charsets.UTF_8));
+
+ context = SensorContextTester.create(new File(dir));
+ context.fileSystem().add(inputFile);
+
+ CxxCpdVisitor cxxCpdVisitor = new CxxCpdVisitor(context);
+ CxxAstScanner.scanSingleFile(inputFile, context, cxxCpdVisitor);
+ }
+
+ @Test
+ public void testCpdTokens() throws Exception {
+ List cpdTokenLines = context.cpdTokens("moduleKey:" + inputFile.file().getName());
+ assertThat(cpdTokenLines).hasSize(75);
+
+ // bits unixtime1(bits ld, bits ex)
+ TokensLine firstTokensLine = cpdTokenLines.get(0);
+ assertThat(firstTokensLine.getValue()).isEqualTo("_I_I(_I_I,_I_I)");
+ assertThat(firstTokensLine.getStartLine()).isEqualTo(2);
+ assertThat(firstTokensLine.getStartUnit()).isEqualTo(1);
+ assertThat(firstTokensLine.getEndLine()).isEqualTo(2);
+ assertThat(firstTokensLine.getEndUnit()).isEqualTo(9);
+
+ // ld &= 0xFF;
+ TokensLine secondTokensLine = cpdTokenLines.get(2);
+ assertThat(secondTokensLine.getValue()).isEqualTo("_I&=_N;");
+ assertThat(secondTokensLine.getStartLine()).isEqualTo(4);
+ assertThat(secondTokensLine.getStartUnit()).isEqualTo(11);
+ assertThat(secondTokensLine.getEndLine()).isEqualTo(4);
+ assertThat(secondTokensLine.getEndUnit()).isEqualTo(14);
+
+ // case 3: return "three";
+ TokensLine thirdTokensLine = cpdTokenLines.get(71);
+ assertThat(thirdTokensLine.getValue()).isEqualTo("case_N:return_S;");
+ assertThat(thirdTokensLine.getStartLine()).isEqualTo(86);
+ assertThat(thirdTokensLine.getStartUnit()).isEqualTo(388);
+ assertThat(thirdTokensLine.getEndLine()).isEqualTo(86);
+ assertThat(thirdTokensLine.getEndUnit()).isEqualTo(393);
+ }
+
+}
diff --git a/sonar-cxx-plugin/src/test/resources/org/sonar/plugins/cxx/cpd.cc b/sonar-cxx-plugin/src/test/resources/org/sonar/plugins/cxx/cpd.cc
new file mode 100644
index 0000000000..e0f48603c0
--- /dev/null
+++ b/sonar-cxx-plugin/src/test/resources/org/sonar/plugins/cxx/cpd.cc
@@ -0,0 +1,89 @@
+//------------------------------------
+bits unixtime1(bits ld, bits ex)
+{
+ ld &= 0xFF;
+ ld -= 51;
+ if (ex < 1855547904U) ld--;
+ ex -= 1855548004U;
+ return ex / 100 + 42949673U * ld - ld / 25;
+}
+
+bits unixtime2(bits ld, bits ex)
+{
+ if (ld && ex)
+ {
+ ld &= 0xFF;
+ ld -= 51;
+ if (ex < 1855547904U) ld--;
+ ex -= 1855548004U;
+ return ex / 100 + 42949673U * ld - ld / 25;
+ }
+ return 0;
+}
+
+//------------------------------------
+int acorntime(bits *ex, bits *ld, time_t utime)
+{
+ unsigned timlo; /* 3 lower bytes of acorn file-time plus carry byte */
+ unsigned timhi; /* 2 high bytes of acorn file-time */
+
+ timlo = ((unsigned)utime & 0x00ffffffU) * 100 + 0x00996a00U;
+ timhi = ((unsigned)utime >> 24);
+ timhi = timhi * 100 + 0x0000336eU + (timlo >> 24);
+ if (timhi & 0xffff0000U)
+ return 1; /* calculation overflow, do not change time */
+
+ /* insert the five time bytes into loadaddr and execaddr variables */
+ *ex = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24);
+ *ld = (*ld & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU);
+
+ return 0; /* subject to future extension to signal overflow */
+}
+
+//------------------------------------
+int object_exists1(char *fn)
+{
+ int ob;
+ if (xosfile_read_stamped_no_path(fn, &ob, 0, 0, 0, 0, 0)) return 0;
+ switch (ob)
+ {
+ case osfile_IS_FILE:return 1;
+ case osfile_IS_DIR:return 1;
+ case osfile_IS_IMAGE:return 1;
+ }
+ return 0;
+}
+
+int object_exists2(char *fn)
+{
+ int ob;
+ if (xosfile_read_stamped_no_path(fn, &ob, 1, 1, 1, 1, 1)) return 1;
+ switch (ob)
+ {
+ case osfile_IS_FILE:return 2;
+ case osfile_IS_DIR:return 2;
+ case osfile_IS_IMAGE:return 2;
+ }
+ return 0;
+}
+
+//------------------------------------
+char* tostring1(int value)
+{
+ switch (value)
+ {
+ case 0: return "zero";
+ case 1: return "one";
+ }
+ return "undefined";
+}
+
+char* tostring2(int value)
+{
+ switch (value)
+ {
+ case 2: return "two";
+ case 3: return "three";
+ }
+ return "undefined";
+}