aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-08-26 12:25:06 +0200
committerChristian Grothoff <christian@grothoff.org>2021-08-26 12:25:06 +0200
commit6bfc7b600b276d4a6c139cdb6b0335ed572332f5 (patch)
tree831f170cb424e30b49d0d20b4d97a0fb6df8ea65
downloadmonkey-6bfc7b600b276d4a6c139cdb6b0335ed572332f5.tar.gz
monkey-6bfc7b600b276d4a6c139cdb6b0335ed572332f5.zip
-recoveredHEADmaster
-rw-r--r--README1
-rw-r--r--doc/man/man1/pathologist.121
-rw-r--r--doc/man/man1/seaspider.115
-rw-r--r--doc/man/man7/monkey.776
-rw-r--r--entomologist/.classpath7
-rw-r--r--entomologist/.fatjar14
-rw-r--r--entomologist/.project17
-rw-r--r--entomologist/.settings/org.eclipse.jdt.core.prefs12
-rw-r--r--entomologist/build.xml26
-rw-r--r--entomologist/comparator.properties29
-rw-r--r--entomologist/entomologist10
-rw-r--r--entomologist/mcomparator.jarbin0 -> 270581 bytes
-rw-r--r--entomologist/src/org/monkey/comparator/BugComparator.java30
-rw-r--r--entomologist/src/org/monkey/comparator/Constants.java65
-rw-r--r--entomologist/src/org/monkey/comparator/Feature.java21
-rw-r--r--entomologist/src/org/monkey/comparator/GeneralPropertiesFeature.java52
-rw-r--r--entomologist/src/org/monkey/comparator/MonkeyComparator.java75
-rw-r--r--entomologist/src/org/monkey/comparator/StackTraceFeature.java167
-rw-r--r--entomologist/src/org/monkey/comparator/Util.java10
-rw-r--r--entomologist/src/org/monkey/comparator/ValueClassifier.java75
-rw-r--r--entomologist/src/org/monkey/comparator/bo/Bug.java44
-rw-r--r--entomologist/src/org/monkey/comparator/bo/Epoch.java24
-rw-r--r--entomologist/src/org/monkey/comparator/bo/Expression.java19
-rw-r--r--entomologist/src/org/monkey/comparator/bo/Function.java38
-rw-r--r--entomologist/src/org/monkey/comparator/bo/XMLParser.java196
-rw-r--r--entomologist/src/org/monkey/comparator/testing/ComparatorTest.java111
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/monkey.xml45
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/monkey_common_and_different_exp.xml47
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/monkey_different_and_longer_history.xml114
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/monkey_different_fname.xml45
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/monkey_different_history.xml60
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/monkey_different_trace.xml61
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/npe.xml29
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/npe_divzero.xml43
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_and_stack_modified.xml42
-rw-r--r--entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_modified.xml37
-rw-r--r--monkey_build_script16
-rw-r--r--pathologist/ABOUT-NLS1068
-rw-r--r--pathologist/AUTHORS0
-rw-r--r--pathologist/COPYING674
-rw-r--r--pathologist/ChangeLog0
-rw-r--r--pathologist/INSTALL365
-rw-r--r--pathologist/Makefile.am11
-rw-r--r--pathologist/NEWS0
-rw-r--r--pathologist/README1
-rwxr-xr-xpathologist/bootstrap8
-rwxr-xr-xpathologist/config.rpath666
-rw-r--r--pathologist/configure.ac221
-rwxr-xr-xpathologist/contrib/monkey_sysinfo.sh228
-rw-r--r--pathologist/m4/ac_define_dir.m435
-rw-r--r--pathologist/m4/libtool.m47377
-rw-r--r--pathologist/m4/ltoptions.m4368
-rw-r--r--pathologist/m4/ltsugar.m4123
-rw-r--r--pathologist/m4/ltversion.m423
-rw-r--r--pathologist/m4/lt~obsolete.m492
-rw-r--r--pathologist/refs/db/bad_memory_access.dbbin0 -> 4096 bytes
-rw-r--r--pathologist/refs/db/bug_assertion_failure.dbbin0 -> 4096 bytes
-rw-r--r--pathologist/refs/db/bug_bad_food.dbbin0 -> 4096 bytes
-rw-r--r--pathologist/refs/db/bug_bad_memory_access.dbbin0 -> 4096 bytes
-rw-r--r--pathologist/refs/db/bug_bug_assertion_failure.db0
-rw-r--r--pathologist/refs/db/bug_division_by_zero_loop.dbbin0 -> 4096 bytes
-rw-r--r--pathologist/refs/db/bug_null_pointer_exception.dbbin0 -> 4096 bytes
-rw-r--r--pathologist/refs/db/bug_null_pointer_exception_modified.dbbin0 -> 6144 bytes
-rw-r--r--pathologist/refs/reports/ref_bt_bug_assertion_failure.xml75
-rw-r--r--pathologist/refs/reports/ref_bt_bug_bad_memory_access.xml103
-rw-r--r--pathologist/refs/reports/ref_bt_bug_division_by_zero_depth_1.xml264
-rw-r--r--pathologist/refs/reports/ref_bt_bug_division_by_zero_nodepth.xml130
-rw-r--r--pathologist/refs/reports/ref_bt_bug_null_pointer_exception.xml79
-rw-r--r--pathologist/refs/reports/ref_bt_bug_null_pointer_exception_modified.xml197
-rw-r--r--pathologist/refs/reports/ref_bug_assertion_failure.xml27
-rw-r--r--pathologist/refs/reports/ref_bug_bad_food.xml46
-rw-r--r--pathologist/refs/reports/ref_bug_bad_memory_access.xml55
-rw-r--r--pathologist/refs/reports/ref_bug_division_by_zero_depth_1.xml30
-rw-r--r--pathologist/refs/reports/ref_bug_division_by_zero_depth_1000.xml30
-rw-r--r--pathologist/refs/reports/ref_bug_division_by_zero_nodepth.xml16
-rw-r--r--pathologist/refs/reports/ref_bug_null_pointer_exception.xml27
-rw-r--r--pathologist/refs/src/Makefile.am41
-rw-r--r--pathologist/refs/src/bug_assertion_failure.c16
-rw-r--r--pathologist/refs/src/bug_bad_food.c11
-rw-r--r--pathologist/refs/src/bug_bad_memory_access.c16
-rw-r--r--pathologist/refs/src/bug_crypto_crc.c121
-rw-r--r--pathologist/refs/src/bug_division_by_zero_loop.c18
-rw-r--r--pathologist/refs/src/bug_null_pointer_exception.c21
-rw-r--r--pathologist/refs/src/bug_null_pointer_exception_modified.c32
-rw-r--r--pathologist/refs/src/bug_sigbus.c50
-rw-r--r--pathologist/src/Makefile.am2
-rw-r--r--pathologist/src/include/Makefile.am9
-rw-r--r--pathologist/src/include/gdbmi.h730
-rw-r--r--pathologist/src/include/monkey_common.h443
-rw-r--r--pathologist/src/include/monkey_getopt_lib.h367
-rw-r--r--pathologist/src/include/mxml.h329
-rw-r--r--pathologist/src/include/platform.h266
-rw-r--r--pathologist/src/include/plibc.h810
-rw-r--r--pathologist/src/mi/Makefile.am29
-rw-r--r--pathologist/src/mi/gdbmi_alloc.c308
-rw-r--r--pathologist/src/mi/gdbmi_breakpoint.c265
-rw-r--r--pathologist/src/mi/gdbmi_connect.c885
-rw-r--r--pathologist/src/mi/gdbmi_data_man.c243
-rw-r--r--pathologist/src/mi/gdbmi_error.c38
-rw-r--r--pathologist/src/mi/gdbmi_get_free_pty.c132
-rw-r--r--pathologist/src/mi/gdbmi_get_free_vt.c156
-rw-r--r--pathologist/src/mi/gdbmi_misc.c118
-rw-r--r--pathologist/src/mi/gdbmi_parse.c1927
-rw-r--r--pathologist/src/mi/gdbmi_prg_control.c598
-rw-r--r--pathologist/src/mi/gdbmi_stack_man.c222
-rw-r--r--pathologist/src/mi/gdbmi_symbol_query.c32
-rw-r--r--pathologist/src/mi/gdbmi_target_man.c119
-rw-r--r--pathologist/src/mi/gdbmi_thread.c89
-rw-r--r--pathologist/src/mi/gdbmi_var_obj.c371
-rw-r--r--pathologist/src/minixml/Makefile.am27
-rw-r--r--pathologist/src/minixml/config.h95
-rw-r--r--pathologist/src/minixml/mxml-attr.c319
-rw-r--r--pathologist/src/minixml/mxml-entity.c460
-rw-r--r--pathologist/src/minixml/mxml-file.c3080
-rw-r--r--pathologist/src/minixml/mxml-get.c471
-rw-r--r--pathologist/src/minixml/mxml-index.c662
-rw-r--r--pathologist/src/minixml/mxml-node.c807
-rw-r--r--pathologist/src/minixml/mxml-private.c331
-rw-r--r--pathologist/src/minixml/mxml-private.h50
-rw-r--r--pathologist/src/minixml/mxml-search.c287
-rw-r--r--pathologist/src/minixml/mxml-set.c349
-rw-r--r--pathologist/src/minixml/mxml-string.c476
-rw-r--r--pathologist/src/minixml/mxmldoc.c5809
-rw-r--r--pathologist/src/pathologist/Makefile.am58
-rw-r--r--pathologist/src/pathologist/action.c1124
-rw-r--r--pathologist/src/pathologist/action.h100
-rw-r--r--pathologist/src/pathologist/edb_api.c368
-rw-r--r--pathologist/src/pathologist/getopt.c1047
-rw-r--r--pathologist/src/pathologist/getopt_helpers.c294
-rw-r--r--pathologist/src/pathologist/mail_sender.c231
-rw-r--r--pathologist/src/pathologist/pathologist.c357
-rw-r--r--pathologist/src/pathologist/pathologist_edb.h158
-rw-r--r--pathologist/src/pathologist/pathologist_xml_writer.h54
-rw-r--r--pathologist/src/pathologist/test_monkey_assertion_failure.sh16
-rw-r--r--pathologist/src/pathologist/test_monkey_bad_memory_access.sh15
-rw-r--r--pathologist/src/pathologist/test_monkey_data.conf43
-rwxr-xr-xpathologist/src/pathologist/test_monkey_npe.sh13
-rw-r--r--pathologist/src/pathologist/test_pathologist.c412
-rw-r--r--pathologist/src/pathologist/xml_writer.c126
-rw-r--r--pathologist/src/struct_parse/exmpl.c31
-rw-r--r--pathologist/src/struct_parse/p.c147
-rw-r--r--pathologist/src/struct_parse/test.sh2
-rw-r--r--pathologist/src/struct_parse/test.txt1
-rw-r--r--pathologist/src/struct_parse/test1.txt1
-rw-r--r--pathologist/src/struct_parse/test2.txt1
-rw-r--r--pathologist/src/struct_parse/test3.txt1
-rw-r--r--pathologist/src/struct_parse/test4.txt1
-rw-r--r--pathologist/src/util/Makefile.am12
-rw-r--r--pathologist/src/util/common_allocation.c338
-rw-r--r--pathologist/src/util/str_replace_all.c56
-rwxr-xr-xseaspider/Makefile3
-rw-r--r--seaspider/ignorefile.example14
-rwxr-xr-xseaspider/remove_inc30
-rwxr-xr-xseaspider/seasp221
-rwxr-xr-xseaspider/seasp2_convert233
155 files changed, 41378 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..b282938
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
Filenames of your source have to be unique, because gdb sometimes gets the whole relative path in the stackframe and sometimes not!
diff --git a/doc/man/man1/pathologist.1 b/doc/man/man1/pathologist.1
new file mode 100644
index 0000000..1fceff8
--- /dev/null
+++ b/doc/man/man1/pathologist.1
@@ -0,0 +1,21 @@
1.TH pathologist 1 2013-03-01 "Monkey Debugging System" "Version 0.1"
2
3.SH NAME
4pathologist \- Automatically generates bug reports.
5
6.SH SYNOPSIS
7.B pathologist -d FILE [ options ] [ -- ] BINARY
8.br
9.B pathologist -h | -v
10
11.SH DESCRIPTION
12With pathologist you can run an application and automatically generate a
13bug report, if the programm crashes. Before you can use pathologist,
14you first have to generate an expression database with seaspider. For more
15information about how to use pathologist as part of the Monkey Debugging
16System see
17.B monkey(7)
18.\.
19
20
21.SH OPTIONS
diff --git a/doc/man/man1/seaspider.1 b/doc/man/man1/seaspider.1
new file mode 100644
index 0000000..e247883
--- /dev/null
+++ b/doc/man/man1/seaspider.1
@@ -0,0 +1,15 @@
1.TH seaspider 1 2013-03-01 "Monkey Debugging System" "Version 0.1"
2
3.SH NAME
4seaspider \- builds an expression database via static code analysis.
5
6.SH SYNOPSIS
7
8.SH DESCRIPTION
9For more information about how to use the generated database with pathologist
10as part of the Monkey Debugging System see
11.B monkey(7)
12.\.
13
14
15.SH OPTIONS
diff --git a/doc/man/man7/monkey.7 b/doc/man/man7/monkey.7
new file mode 100644
index 0000000..9087f8a
--- /dev/null
+++ b/doc/man/man7/monkey.7
@@ -0,0 +1,76 @@
1.TH monkey 7 2013-03-01 "Monkey Debugging System" "Version 0.1"
2
3.SH NAME
4monkey \- An automated debugging tool.
5
6.SH DESCRIPTION
7.P
8The Monkey Debugging System is a three part toolset for automtically generating
9bug reports from program crashes.
10.P
11To allow automated crash analysis with pathologist, you first have to generate
12an expression database with
13.B seaspider(1)
14. Seaspider will do some static code analysis and generate a sqlite database
15file containing all the expressions in your source code. If you have
16some variables in your source code which contain private information
17of the user that must not be included in bug reports, you can specify
18an ignore file which contains regular expressions to exclude those
19variables from the database, and therefore prevent later appearance of
20the private data in the bug report.
21
22.P
23After the expression database has been generated, you can ship this database
24together with your application. On the target system, the user can then use
25.B pathologist(1)
26, to run your application under supervision using
27.B gdb(1)
28. If the application crashes,
29a post-mortem analysis will be performed. The stack will be analyzed and all relevant
30expressions in the stacktrace and other information about the crash will be evaluated and written to a bug report
31in XML format. When the report has been succesfully written, Pathologist can
32send the report to the developer via mail.
33
34.P
35The third component of the monkey debugging system is the
36.B entomologist(1)
37, which is not yet functional. The Entomologist but will provide comparison and clustering algorithms
38for the generated reports.
39
40.SH REQUIREMENTS
41.P
42To use the Monkey Debugging System, you have to fulfill the following
43requirements.
44
45.P
46Your project has to be written in C (C++ support is missing in Seaspider).
47
48.P
49To use Seaspider, your project has to be built with GNU Autotools. Other Build
50Systems are not supported, but it should still be possible to use them as well,
51if you can set the compiler and compiler options yourself.
52
53.P
54You need gdb in version 7 or later, and we have only tested the system on GNU/Linux.
55
56.SH LIMITATIONS
57.P
58Pathologist can only (nicely) handle the following signals at this time: SIGSEGV (Segfault),
59SIGABRT (Assertion), SIGBUS (Bad Memory Access), and SIGFPE (Arithmetic Exception).
60
61.P
62Your C source file names have to be globally unique in your project.
63
64.P
65Due to gdb changing the respective values on the stack while evaluating,
66increments and decrements are problematic if contained in the line of code,
67which causes the crash. Seaspider will just remove every single increment and
68decrement operator before writing expressions to the database, so if your
69program crashes on a line
70.B a = b[++c];
71, the report will only contain the
72value of
73.B b[c]
74.
75
76
diff --git a/entomologist/.classpath b/entomologist/.classpath
new file mode 100644
index 0000000..b10b8d9
--- /dev/null
+++ b/entomologist/.classpath
@@ -0,0 +1,7 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<classpath>
3 <classpathentry kind="src" path="src"/>
4 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
5 <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
6 <classpathentry kind="output" path="bin"/>
7</classpath>
diff --git a/entomologist/.fatjar b/entomologist/.fatjar
new file mode 100644
index 0000000..ce6d1ab
--- /dev/null
+++ b/entomologist/.fatjar
@@ -0,0 +1,14 @@
1#Fat Jar Configuration File
2#Sun Jul 15 12:40:42 CEST 2012
3onejar.license.required=true
4manifest.classpath=
5manifest.removesigners=true
6onejar.checkbox=false
7jarname=mcomparator.jar
8manifest.mergeall=true
9manifest.mainclass=org.monkey.comparator.MonkeyComparator
10manifest.file=<createnew>
11jarname.isextern=false
12onejar.expand=
13excludes=
14includes=
diff --git a/entomologist/.project b/entomologist/.project
new file mode 100644
index 0000000..84d2b8a
--- /dev/null
+++ b/entomologist/.project
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<projectDescription>
3 <name>MonkeyBugComparator</name>
4 <comment></comment>
5 <projects>
6 </projects>
7 <buildSpec>
8 <buildCommand>
9 <name>org.eclipse.jdt.core.javabuilder</name>
10 <arguments>
11 </arguments>
12 </buildCommand>
13 </buildSpec>
14 <natures>
15 <nature>org.eclipse.jdt.core.javanature</nature>
16 </natures>
17</projectDescription>
diff --git a/entomologist/.settings/org.eclipse.jdt.core.prefs b/entomologist/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..9e22754
--- /dev/null
+++ b/entomologist/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
1#Tue Jan 24 16:34:26 CET 2012
2eclipse.preferences.version=1
3org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
4org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
5org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
6org.eclipse.jdt.core.compiler.compliance=1.6
7org.eclipse.jdt.core.compiler.debug.lineNumber=generate
8org.eclipse.jdt.core.compiler.debug.localVariable=generate
9org.eclipse.jdt.core.compiler.debug.sourceFile=generate
10org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
11org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
12org.eclipse.jdt.core.compiler.source=1.6
diff --git a/entomologist/build.xml b/entomologist/build.xml
new file mode 100644
index 0000000..3d99b77
--- /dev/null
+++ b/entomologist/build.xml
@@ -0,0 +1,26 @@
1<?xml version="1.0"?>
2<project name="FatJar mcomparator.jar (experimental)" default="main" basedir=".">
3 <!-- this file was created by Fat-Jar Eclipse Plug-in -->
4 <!-- the ANT-Export is in a very early stage, so this -->
5 <!-- is only experimental, ANT 1.6 or above is -->
6 <!-- required, feedback is always welcome: -->
7 <!-- http://sourceforge.net/projects/fjep -->
8 <!-- uncomment the following lines if using ANT outside Eclipse -->
9 <!--
10 <property name="fjepPath" value="reference:file:plugins/net.sf.fjep.fatjar_0.0.31/fatjar.jar"/>
11 <taskdef name="fatjar.build" classname="net.sf.fjep.anttask.FJBuildTask" classpath="${fjepPath}"/>
12 <typedef name="fatjar.manifest" classname="net.sf.fjep.anttask.FJManifestType" classpath="${fjepPath}"/>
13 <typedef name="fatjar.exclude" classname="net.sf.fjep.anttask.FJExcludeType" classpath="${fjepPath}"/>
14 <typedef name="fatjar.jarsource" classname="net.sf.fjep.anttask.FJJarSourceType" classpath="${fjepPath}"/>
15 <typedef name="fatjar.filesource" classname="net.sf.fjep.anttask.FJFileSourceType" classpath="${fjepPath}"/>
16 -->
17 <!-- uncomment the above lines to use ANT outside of Eclipse -->
18 <target name="main">
19 <fatjar.build output="mcomparator.jar">
20 <fatjar.manifest mainclass="org.monkey.comparator.MonkeyComparator"/>
21 <fatjar.filesource path="/home/safey/EclipseWorkspaceMonkeyComparator/MonkeyBugComparator/bin" relpath="">
22 <fatjar.exclude relpath="org/monkey/comparator/testing/"/>
23 </fatjar.filesource>
24 </fatjar.build>
25 </target>
26</project>
diff --git a/entomologist/comparator.properties b/entomologist/comparator.properties
new file mode 100644
index 0000000..0c4f95f
--- /dev/null
+++ b/entomologist/comparator.properties
@@ -0,0 +1,29 @@
1MAX_INT=2147483647
2MIN_INT=-2147483647
3ENABLE_VALUE_CLASSES=false
4LINE_NUMBER_DIFFERENCE_THRESHOLD=10
5
6# Features' scores
7GENERAL_PROPERTIES_FEATURE_SCORE=100
8STACK_TRACE_FEATURE_SCORE=50
9
10# Weights for feature: Bug General Properties
11BUG_CATEGORY_WEIGHT=0.75
12LINE_NUMBER_WEIGHT=0.00625
13BUG_FUNCTION_NAME_WEIGHT=0.1875
14FILE_NAME_WEIGHT=0.05625
15
16# Weights for feature: Stack-Trace
17# Weight of all function semantics in the stack-trace (function name, file name, line number)
18FUNCTION_SEMANTICS_WEIGHT=0.1
19# Weight of all expressions in the stack-trace
20EXPRESSIONS_WEIGHT=0.9
21
22# Within the function semantics
23FUNCTION_NAME_WEIGHT=0.25
24FUNCTION_LINE_WEIGHT=0.25
25FUNCTION_FILE_NAME=0.5
26
27# Within the expressions of the function
28EXPRESSION_SYTNAX_WEIGHT=0.7
29EXPRESSION_VALUE_WEIGHT=0.3
diff --git a/entomologist/entomologist b/entomologist/entomologist
new file mode 100644
index 0000000..ac3ca9f
--- /dev/null
+++ b/entomologist/entomologist
@@ -0,0 +1,10 @@
1#! /bin/bash
2
3echo "Wrapper for the Monkey bug comparator (entomologist)"
4if ls mcomparator.jar &> /dev/null; then
5 java -jar mcomparator.jar $1 $2 $3 $4
6else
7 echo "Run: entomologist file1.xml file2.xml -p comparator.properties"
8 echo "mcomparator.jar must be in the same directory of this script."
9fi
10
diff --git a/entomologist/mcomparator.jar b/entomologist/mcomparator.jar
new file mode 100644
index 0000000..be6a8d4
--- /dev/null
+++ b/entomologist/mcomparator.jar
Binary files differ
diff --git a/entomologist/src/org/monkey/comparator/BugComparator.java b/entomologist/src/org/monkey/comparator/BugComparator.java
new file mode 100644
index 0000000..d89af84
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/BugComparator.java
@@ -0,0 +1,30 @@
1package org.monkey.comparator;
2
3import java.util.ArrayList;
4
5public class BugComparator {
6 private static ArrayList<Feature> featureList = new ArrayList<Feature>();
7
8 public static boolean register(Feature feature) {
9 featureList.add(feature);
10 return true;
11 }
12
13 public static boolean unregister(Feature feature) {
14 featureList.remove(feature);
15 return true;
16 }
17
18 public static double calculateScore() {
19 double totalScore = 0;
20 double featureScore;
21 Feature feature;
22 for (int i = 0; i < featureList.size(); i++) {
23 feature = featureList.get(i);
24 featureScore = feature.score();
25 //System.out.println(feature.getFeatureName() + " score = " + featureScore);
26 totalScore += featureScore;
27 }
28 return totalScore;
29 }
30}
diff --git a/entomologist/src/org/monkey/comparator/Constants.java b/entomologist/src/org/monkey/comparator/Constants.java
new file mode 100644
index 0000000..f707fdf
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/Constants.java
@@ -0,0 +1,65 @@
1package org.monkey.comparator;
2
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.IOException;
6import java.util.Properties;
7
8public abstract class Constants {
9 public static int MAX_INT;
10 public static int MIN_INT;
11 public static boolean ENABLE_VALUE_CLASSES;
12 public static int LINE_NUMBER_DIFFERENCE_THRESHOLD;
13
14 /* Features' scores */
15 public static double GENERAL_PROPERTIES_FEATURE_SCORE;
16 public static double STACK_TRACE_FEATURE_SCORE;
17
18 /* Weights for feature: Bug General Properties */
19 public static double BUG_CATEGORY_WEIGHT;
20 public static double LINE_NUMBER_WEIGHT;
21 public static double BUG_FUNCTION_NAME_WEIGHT;
22 public static double FILE_NAME_WEIGHT;
23
24 /* Weights for feature: Stack-Trace */
25 public static double FUNCTION_SEMANTICS_WEIGHT; // Weight of all function semantics in the stack-trace (function name, file name, line number)
26 public static double EXPRESSIONS_WEIGHT; // Weight of all expressions in the stack-trace
27
28 public static double FUNCTION_NAME_WEIGHT; // Within the function semantics
29 public static double FUNCTION_LINE_WEIGHT;
30 public static double FUNCTION_FILE_NAME;
31
32 public static double EXPRESSION_SYTNAX_WEIGHT; // Within the expressions of the function
33 public static double EXPRESSION_VALUE_WEIGHT;
34
35 public static void setUpConstants(String propertiesFilePath) {
36 Properties properties = new Properties();
37 try {
38 properties.load(new FileInputStream(propertiesFilePath));
39 MAX_INT = Integer.parseInt(properties.getProperty("MAX_INT"));
40 MIN_INT = Integer.parseInt(properties.getProperty("MIN_INT"));
41 ENABLE_VALUE_CLASSES = Boolean.parseBoolean(properties.getProperty("ENABLE_VALUE_CLASSES"));
42 LINE_NUMBER_DIFFERENCE_THRESHOLD = Integer.parseInt(properties.getProperty("LINE_NUMBER_DIFFERENCE_THRESHOLD"));
43 GENERAL_PROPERTIES_FEATURE_SCORE = Double.parseDouble(properties.getProperty("GENERAL_PROPERTIES_FEATURE_SCORE"));
44 STACK_TRACE_FEATURE_SCORE = Double.parseDouble(properties.getProperty("STACK_TRACE_FEATURE_SCORE"));
45 BUG_CATEGORY_WEIGHT = Double.parseDouble(properties.getProperty("BUG_CATEGORY_WEIGHT"));
46 LINE_NUMBER_WEIGHT = Double.parseDouble(properties.getProperty("LINE_NUMBER_WEIGHT"));
47 BUG_FUNCTION_NAME_WEIGHT = Double.parseDouble(properties.getProperty("BUG_FUNCTION_NAME_WEIGHT"));
48 FILE_NAME_WEIGHT = Double.parseDouble(properties.getProperty("FILE_NAME_WEIGHT"));
49 FUNCTION_SEMANTICS_WEIGHT = Double.parseDouble(properties.getProperty("FUNCTION_SEMANTICS_WEIGHT"));
50 EXPRESSIONS_WEIGHT = Double.parseDouble(properties.getProperty("EXPRESSIONS_WEIGHT"));
51 FUNCTION_NAME_WEIGHT = Double.parseDouble(properties.getProperty("FUNCTION_NAME_WEIGHT"));
52 FUNCTION_LINE_WEIGHT = Double.parseDouble(properties.getProperty("FUNCTION_LINE_WEIGHT"));
53 FUNCTION_FILE_NAME = Double.parseDouble(properties.getProperty("FUNCTION_FILE_NAME"));
54 EXPRESSION_SYTNAX_WEIGHT = Double.parseDouble(properties.getProperty("EXPRESSION_SYTNAX_WEIGHT"));
55 EXPRESSION_VALUE_WEIGHT = Double.parseDouble(properties.getProperty("EXPRESSION_VALUE_WEIGHT"));
56 } catch (FileNotFoundException e) {
57 e.printStackTrace();
58 } catch (IOException e) {
59 System.err.println("Fatal error: unable to read properties. Entomologist will exit now.");
60 e.printStackTrace();
61 System.exit(1);
62 }
63 }
64
65}
diff --git a/entomologist/src/org/monkey/comparator/Feature.java b/entomologist/src/org/monkey/comparator/Feature.java
new file mode 100644
index 0000000..576ac44
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/Feature.java
@@ -0,0 +1,21 @@
1package org.monkey.comparator;
2
3import org.monkey.comparator.bo.Bug;
4
5public abstract class Feature {
6 protected Bug bugA;
7 protected Bug bugB;
8 protected String featureName = "Feature";
9 protected double featureTotalScore = 0;
10
11 public Feature (Bug bugA, Bug bugB, double featureTotalScore) {
12 this.bugA = bugA;
13 this.bugB = bugB;
14 this.featureTotalScore = featureTotalScore;
15 }
16
17 protected abstract String getFeatureName();
18 protected abstract void assignScorePoints();
19 public abstract double score();
20}
21
diff --git a/entomologist/src/org/monkey/comparator/GeneralPropertiesFeature.java b/entomologist/src/org/monkey/comparator/GeneralPropertiesFeature.java
new file mode 100644
index 0000000..ac4282c
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/GeneralPropertiesFeature.java
@@ -0,0 +1,52 @@
1package org.monkey.comparator;
2
3import org.monkey.comparator.bo.Bug;
4
5public class GeneralPropertiesFeature extends Feature {
6 private static double bugCategoryScore;
7 private static double lineNumberScore;
8 private static double functionNameScore;
9 private static double fileNameScore;
10
11 public GeneralPropertiesFeature(Bug bugA, Bug bugB, double featureTotalScore) {
12 super(bugA, bugB, featureTotalScore);
13 featureName = "Feature: Bug General Properties";
14 }
15
16 private double compareGeneralProperties() {
17 double score = 0;
18 if (bugA.getCategory().equals(bugB.getCategory()))
19 score += bugCategoryScore;
20 if (bugA.getFileName().equals(bugB.getFileName()))
21 score += fileNameScore;
22 if (bugA.getFunctionName().equals(bugB.getFunctionName()))
23 score += functionNameScore;
24 if (bugA.getLineNo() == bugB.getLineNo()) {
25 score += lineNumberScore;
26 } else {
27 score += Util.weightLineNumberDifference(bugA.getLineNo(), bugB.getLineNo()) * lineNumberScore;
28 }
29
30 return score;
31 }
32
33 @Override
34 public double score() {
35 assignScorePoints();
36 return compareGeneralProperties();
37 }
38
39 @Override
40 protected void assignScorePoints() {
41 bugCategoryScore = Constants.BUG_CATEGORY_WEIGHT * featureTotalScore;
42 lineNumberScore = Constants.LINE_NUMBER_WEIGHT * featureTotalScore;
43 functionNameScore = Constants.BUG_FUNCTION_NAME_WEIGHT * featureTotalScore;
44 fileNameScore = Constants.FILE_NAME_WEIGHT * featureTotalScore;
45 }
46
47 @Override
48 protected String getFeatureName() {
49 return featureName;
50 }
51
52}
diff --git a/entomologist/src/org/monkey/comparator/MonkeyComparator.java b/entomologist/src/org/monkey/comparator/MonkeyComparator.java
new file mode 100644
index 0000000..82428a2
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/MonkeyComparator.java
@@ -0,0 +1,75 @@
1package org.monkey.comparator;
2
3import java.io.File;
4import org.monkey.comparator.bo.Bug;
5import org.monkey.comparator.bo.XMLParser;
6
7public class MonkeyComparator {
8 public static double compareBugs(Bug bugA, Bug bugB, String propertiesFilePath) {
9 Constants.setUpConstants(propertiesFilePath);
10
11 double similarityPercentage = 0;
12 double totalScore = Constants.GENERAL_PROPERTIES_FEATURE_SCORE + Constants.STACK_TRACE_FEATURE_SCORE;
13
14 /* Register comparison features and start comparison */
15 Feature generalPropertiesFeature = new GeneralPropertiesFeature(bugA, bugB, Constants.GENERAL_PROPERTIES_FEATURE_SCORE);
16 Feature stackTraceFeature = new StackTraceFeature(bugA, bugB, Constants.STACK_TRACE_FEATURE_SCORE);
17
18 BugComparator.register(generalPropertiesFeature);
19 BugComparator.register(stackTraceFeature);
20 similarityPercentage = (BugComparator.calculateScore() / totalScore) * 100;
21
22 /* Cleanup */
23 BugComparator.unregister(generalPropertiesFeature);
24 BugComparator.unregister(stackTraceFeature);
25
26 return similarityPercentage;
27 }
28
29 private static void showErrorAndExit() {
30 System.err.println("Monkey Bug Comparator takes the following arguments: " +
31 "file1.xml file2.xml -p configuration.properties");
32 System.exit(1);
33 }
34
35 private static boolean checkFilePath(String filePath) {
36 if (new File(filePath).exists() == false) {
37 System.err.println("File " + filePath + " not found!");
38 showErrorAndExit();
39 }
40 return true;
41 }
42 public static void main(String[] args) {
43 String propertiesFilePath = null;
44 String bugAFilePath = null;
45 String bugBFilePath = null;
46
47 if (args.length < 4)
48 showErrorAndExit();
49
50 for (int i = 0; i < args.length; i++) {
51 if (args[i].equals("-p")) {
52 propertiesFilePath = args[++i];
53 checkFilePath(propertiesFilePath);
54 }
55 else if (null == bugAFilePath) {
56 bugAFilePath = args[i];
57 checkFilePath(bugAFilePath);
58 }
59 else if (null == bugBFilePath) {
60 bugBFilePath = args[i];
61 checkFilePath(bugBFilePath);
62 }
63 }
64
65 if (null == propertiesFilePath || null == bugAFilePath || null == bugBFilePath)
66 showErrorAndExit();
67
68 Bug bugA = XMLParser.parse(bugAFilePath);
69 Bug bugB = XMLParser.parse(bugBFilePath);
70 //XMLParser.printBug(bugA);
71 //XMLParser.printBug(bugB);
72
73 System.out.println("Similarity Percentage = " + compareBugs(bugA, bugB, propertiesFilePath));
74 }
75}
diff --git a/entomologist/src/org/monkey/comparator/StackTraceFeature.java b/entomologist/src/org/monkey/comparator/StackTraceFeature.java
new file mode 100644
index 0000000..f2b13eb
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/StackTraceFeature.java
@@ -0,0 +1,167 @@
1package org.monkey.comparator;
2
3
4import org.monkey.comparator.bo.Bug;
5import org.monkey.comparator.bo.Epoch;
6import org.monkey.comparator.bo.Expression;
7import org.monkey.comparator.bo.Function;
8
9public class StackTraceFeature extends Feature {
10 private double functionNameScore;
11 private double functionLineNumberScore;
12 private double functionFileNameScore;
13 private double expressionSyntaxScore;
14 private double expressionValueScore;
15 private int functionNum;
16 private int expressionNum;
17 private int epochNum;
18
19 public StackTraceFeature(Bug bugA, Bug bugB, double featureTotalScore) {
20 super(bugA, bugB, featureTotalScore);
21 featureName = "Feature: Stack-Trace";
22 }
23
24 private double compareFunctions(int epochIndex) {
25 int numFunctionA = bugA.getEpoch(epochIndex).getFunctionNum();
26 int numFunctionB = bugB.getEpoch(epochIndex).getFunctionNum();
27
28 if (numFunctionA >= numFunctionB)
29 return doCompareFunctions(bugB.getEpoch(epochIndex), bugA.getEpoch(epochIndex));
30 return doCompareFunctions(bugA.getEpoch(epochIndex), bugB.getEpoch(epochIndex));
31 }
32
33 private double doCompareFunctions(Epoch shorterEpoch, Epoch longerEpoch) {
34 double functionsScore = 0;
35 double expressionsScore = 0;
36 double tmpExpressionScore = 0;
37
38 int numFunctionShorter = shorterEpoch.getFunctionNum();
39 int numFunctionLonger = longerEpoch.getFunctionNum();
40 Function functionShorterEpoch;
41 Function functionLongerEpoch;
42 for (int i = 0; i < numFunctionShorter; i++) {
43 functionShorterEpoch = shorterEpoch.getFunction(i);
44 for (int j = 0; j < numFunctionLonger; j++) {
45 functionLongerEpoch = longerEpoch.getFunction(j);
46
47 tmpExpressionScore = compareExpressions(functionShorterEpoch, functionLongerEpoch);
48 expressionsScore += tmpExpressionScore;
49 if (tmpExpressionScore > 0) {
50 if (functionShorterEpoch.getLineNo() == functionLongerEpoch.getLineNo()) {
51 functionsScore += functionLineNumberScore;
52 } else {
53 /* If there is some similarity in expressions,
54 * but function line numbers are not the same,
55 * score for function line numbers should NOT be zero */
56 functionsScore += Util.weightLineNumberDifference(functionShorterEpoch.getLineNo(), functionLongerEpoch.getLineNo())
57 * functionLineNumberScore;
58 }
59 if(functionShorterEpoch.getFileName().equals(functionLongerEpoch.getFileName()))
60 functionsScore += functionFileNameScore;
61 if(functionShorterEpoch.getFunctionName().equals(functionLongerEpoch.getFunctionName()))
62 functionsScore += functionNameScore;
63 break;
64 }
65 }
66 }
67 return functionsScore + expressionsScore;
68 }
69
70 private double compareExpressions(Function functionA, Function functionB) {
71 int numExpressionA = functionA.getExpressionNum();
72 int numExpressionB = functionB.getExpressionNum();
73
74 if (numExpressionA >= numExpressionB)
75 return doCompareExpressions(functionB, functionA);
76 return doCompareExpressions(functionA, functionB);
77 }
78
79 private double doCompareExpressions(Function shorterFunction, Function longerFunction) {
80 double expressionsScore = 0;
81 int numExpressionShorter = shorterFunction.getExpressionNum();
82 int numExpressionLonger = longerFunction.getExpressionNum();
83
84 Expression expressionShorterFunction;
85 Expression expressionLongerFunction;
86 for (int i = 0; i < numExpressionShorter; i++) {
87 expressionShorterFunction = shorterFunction.getExpression(i);
88 for (int j = 0; j < numExpressionLonger; j++) {
89 expressionLongerFunction = longerFunction.getExpression(j);
90 if (expressionShorterFunction.getName().equals(expressionLongerFunction.getName())) {
91 expressionsScore += expressionSyntaxScore;
92 if (ValueClassifier.classify(expressionShorterFunction.getValue(), expressionLongerFunction.getValue()))
93 expressionsScore += expressionValueScore;
94 break; // break inner loop
95 }
96 }
97 }
98
99 return expressionsScore;
100 }
101
102 @Override
103 public double score() {
104 assignScorePoints();
105 double finalScore = 0.0;
106 for (int i = 0; i < epochNum; i++)
107 finalScore += compareFunctions(i);
108 return finalScore;
109 }
110
111 @Override
112 protected void assignScorePoints() {
113 int epochNumA = bugA.getEpochNum();
114 int epochNumB = bugB.getEpochNum();
115 epochNum = epochNumA <= epochNumB ? epochNumA : epochNumB; // compare the smallest number of epoch steps
116
117 int expressionNumA, expressionNumB, functionNumA, functionNumB;
118 Function function;
119 for (int i = 0; i < epochNum; i++) {
120 functionNumA = bugA.getEpoch(i).getFunctionNum();
121 functionNumB = bugB.getEpoch(i).getFunctionNum();
122 functionNum += functionNumA >= functionNumB ? functionNumA : functionNumB; // taking the larger number of functions of the two stack traces
123
124 expressionNumA = 0;
125 for (int j = 0; j < functionNumA; j++) {
126 function = bugA.getEpoch(i).getFunction(j);
127 expressionNumA += function.getExpressionNum();
128 }
129
130 expressionNumB = 0;
131 for (int j = 0; j < functionNumB; j++) {
132 function = bugB.getEpoch(i).getFunction(j);
133 expressionNumB += function.getExpressionNum();
134 }
135
136 expressionNum += expressionNumA >= expressionNumB ? expressionNumA : expressionNumB; // taking the larger number of expressions of the two stack traces
137 }
138
139
140 double allFunctionSemanticsScore = Constants.FUNCTION_SEMANTICS_WEIGHT * featureTotalScore;
141 double singleFunctionSemanticsScore = (double)allFunctionSemanticsScore / (double)functionNum;
142 double allExpressionsScore = Constants.EXPRESSIONS_WEIGHT * featureTotalScore;
143 double singleExpressionScore = (double)allExpressionsScore / (double)expressionNum;
144
145 /* Scoring for function semantics details */
146 functionNameScore = Constants.FUNCTION_NAME_WEIGHT *singleFunctionSemanticsScore;
147 functionFileNameScore = Constants.FUNCTION_FILE_NAME * singleFunctionSemanticsScore;
148 functionLineNumberScore = Constants.FUNCTION_LINE_WEIGHT * singleFunctionSemanticsScore;
149
150 /* Scoring for expression semantics details */
151 expressionSyntaxScore = Constants.EXPRESSION_SYTNAX_WEIGHT * singleExpressionScore;
152 expressionValueScore = Constants.EXPRESSION_VALUE_WEIGHT * singleExpressionScore;
153 }
154
155
156 @Override
157 protected String getFeatureName() {
158 return featureName;
159 }
160
161 /*
162 private double testTotalScore() {
163 return ((functionNameScore + functionFileNameScore + functionLineNumberScore) * functionNum) + ((expressionSyntaxScore + expressionValueScore) * expressionNum);
164 }
165 */
166
167}
diff --git a/entomologist/src/org/monkey/comparator/Util.java b/entomologist/src/org/monkey/comparator/Util.java
new file mode 100644
index 0000000..7f3f0c3
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/Util.java
@@ -0,0 +1,10 @@
1package org.monkey.comparator;
2
3public abstract class Util {
4 public static double weightLineNumberDifference(int lineNumberA, int lineNumberB) {
5 double diff = Math.abs(lineNumberA - lineNumberB);
6 double div = diff/(double)Constants.LINE_NUMBER_DIFFERENCE_THRESHOLD;
7 double weight = 1 - div;
8 return weight;
9 }
10}
diff --git a/entomologist/src/org/monkey/comparator/ValueClassifier.java b/entomologist/src/org/monkey/comparator/ValueClassifier.java
new file mode 100644
index 0000000..a81eafb
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/ValueClassifier.java
@@ -0,0 +1,75 @@
1package org.monkey.comparator;
2
3public class ValueClassifier {
4 public static boolean classify(String expressionValueA, String expressionValueB) {
5 /* If value classes disabled compare values normally and return */
6 if (Constants.ENABLE_VALUE_CLASSES == false) {
7 if (expressionValueA.equals(expressionValueB))
8 return true;
9 return false;
10 }
11
12 /* Value classes enabled */
13 if (((expressionValueA.startsWith("0x") || expressionValueA.equals("NULL"))
14 && (expressionValueB.startsWith("0x") || expressionValueB.equals("NULL")))) {
15 return classifyPointer(expressionValueA, expressionValueB);
16 }
17 try {
18 int iA = Integer.parseInt(expressionValueA);
19 int iB = Integer.parseInt(expressionValueB);
20 return classifyInteger(iA, iB);
21 }
22 catch (NumberFormatException e) {
23 try {
24 float fA = Float.parseFloat(expressionValueA);
25 float fB = Float.parseFloat(expressionValueB);
26 return classifyFloat(fA, fB);
27 }
28 catch (NumberFormatException ee) {
29 return classifyString(expressionValueA, expressionValueB);
30 }
31 }
32 }
33
34 private static boolean classifyInteger(int expressionAValue, int expressionBValue) {
35 if (expressionAValue == 0 || expressionBValue == 0 ||
36 expressionAValue == 1 || expressionBValue == 1
37 || expressionAValue == -1 || expressionBValue == -1 ||
38 expressionAValue == Constants.MAX_INT || expressionBValue == Constants.MAX_INT ||
39 expressionAValue == Constants.MIN_INT || expressionBValue == Constants.MIN_INT) {
40 if (expressionAValue == expressionBValue)
41 return true;
42 return false;
43 }
44 return true;
45 }
46
47 private static boolean classifyFloat(float bugAValue, float bugBValue) {
48 if (bugAValue == 0.0 || bugBValue == 0.0) {
49 if (bugAValue == bugBValue)
50 return true;
51 return false;
52 }
53 return true;
54 }
55
56 private static boolean classifyPointer(String bugAValue, String bugBValue) {
57 if (bugAValue.equals("NULL") || bugBValue.equals("NULL")) {
58 if (bugAValue.equals(bugBValue))
59 return true;
60 return false;
61 }
62 return true;
63 }
64
65 private static boolean classifyString(String bugAValue, String bugBValue) {
66 if (bugAValue.equals("NULL") || bugAValue.equals("")
67 || bugBValue.equals("NULL") || bugBValue.equals("")) {
68 if (bugAValue.equals(bugBValue)) {
69 return true;
70 }
71 return false;
72 }
73 return true;
74 }
75}
diff --git a/entomologist/src/org/monkey/comparator/bo/Bug.java b/entomologist/src/org/monkey/comparator/bo/Bug.java
new file mode 100644
index 0000000..62f4d24
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/bo/Bug.java
@@ -0,0 +1,44 @@
1package org.monkey.comparator.bo;
2
3import java.util.ArrayList;
4
5public class Bug {
6 private String category;
7 private String fileName;
8 private int lineNo;
9 private String functionName;
10 private ArrayList<Epoch> epochList = new ArrayList<Epoch>();
11 public void setFileName(String fileName) {
12 this.fileName = fileName;
13 }
14 public String getFileName() {
15 return fileName;
16 }
17 public void setLineNo(int lineNo) {
18 this.lineNo = lineNo;
19 }
20 public int getLineNo() {
21 return lineNo;
22 }
23 public void setFunctionName(String functionName) {
24 this.functionName = functionName;
25 }
26 public String getFunctionName() {
27 return functionName;
28 }
29 public void insertEpoch(Epoch epoch) {
30 this.epochList.add(epoch);
31 }
32 public Epoch getEpoch(int index) {
33 return epochList.get(index);
34 }
35 public void setCategory(String category) {
36 this.category = category;
37 }
38 public String getCategory() {
39 return category;
40 }
41 public int getEpochNum() {
42 return epochList.size();
43 }
44}
diff --git a/entomologist/src/org/monkey/comparator/bo/Epoch.java b/entomologist/src/org/monkey/comparator/bo/Epoch.java
new file mode 100644
index 0000000..71e2554
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/bo/Epoch.java
@@ -0,0 +1,24 @@
1package org.monkey.comparator.bo;
2
3import java.util.ArrayList;
4
5public class Epoch {
6 private int epochStep;
7 private ArrayList<Function> functionList = new ArrayList<Function>();
8
9 public void setEpochStep(int epochStep) {
10 this.epochStep = epochStep;
11 }
12 public int getEpochStep() {
13 return epochStep;
14 }
15 public void insertFunction(Function function) {
16 this.functionList.add(function);
17 }
18 public Function getFunction(int index) {
19 return functionList.get(index);
20 }
21 public int getFunctionNum() {
22 return functionList.size();
23 }
24}
diff --git a/entomologist/src/org/monkey/comparator/bo/Expression.java b/entomologist/src/org/monkey/comparator/bo/Expression.java
new file mode 100644
index 0000000..7903189
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/bo/Expression.java
@@ -0,0 +1,19 @@
1package org.monkey.comparator.bo;
2
3public class Expression {
4 private String name;
5 private String value;
6 public void setName(String name) {
7 this.name = name;
8 }
9 public String getName() {
10 return name;
11 }
12 public void setValue(String value) {
13 this.value = value;
14 }
15 public String getValue() {
16 return value;
17 }
18
19}
diff --git a/entomologist/src/org/monkey/comparator/bo/Function.java b/entomologist/src/org/monkey/comparator/bo/Function.java
new file mode 100644
index 0000000..f6adbd2
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/bo/Function.java
@@ -0,0 +1,38 @@
1package org.monkey.comparator.bo;
2
3import java.util.ArrayList;
4
5public class Function {
6 private String functionName;
7 private int lineNo;
8 private String fileName;
9 private ArrayList<Expression> expressionList = new ArrayList<Expression>();
10
11 public void setFunctionName(String functionName) {
12 this.functionName = functionName;
13 }
14 public String getFunctionName() {
15 return functionName;
16 }
17 public void setLineNo(int lineNo) {
18 this.lineNo = lineNo;
19 }
20 public int getLineNo() {
21 return lineNo;
22 }
23 public void insertExpression(Expression expression) {
24 this.expressionList.add(expression);
25 }
26 public Expression getExpression(int index) {
27 return expressionList.get(index);
28 }
29 public String getFileName() {
30 return fileName;
31 }
32 public void setFileName(String fileName) {
33 this.fileName = fileName;
34 }
35 public int getExpressionNum() {
36 return expressionList.size();
37 }
38}
diff --git a/entomologist/src/org/monkey/comparator/bo/XMLParser.java b/entomologist/src/org/monkey/comparator/bo/XMLParser.java
new file mode 100644
index 0000000..6254730
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/bo/XMLParser.java
@@ -0,0 +1,196 @@
1package org.monkey.comparator.bo;
2
3import java.io.File;
4
5import javax.xml.parsers.DocumentBuilder;
6import javax.xml.parsers.DocumentBuilderFactory;
7
8import org.w3c.dom.Document;
9import org.w3c.dom.Element;
10import org.w3c.dom.Node;
11import org.w3c.dom.NodeList;
12
13public class XMLParser {
14
15 /*
16 * The method parses Monkey's XML Bug Report.
17 * The following is an example the XML file the method expects for parsing
18 * <?xml version="1.0"?>
19 <crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
20 <history>
21 <epoch step="0" >
22 <trace>
23 <function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
24 <expressions>
25 <expression name="crashStruct" >NULL</expression>
26 </expressions>
27 </function>
28 </trace>
29 </epoch>
30 </history>
31 </crash>
32 */
33 public static Bug parse(String filePath) {
34 Bug bug = new Bug();
35 try {
36 NodeList epochNodeList;
37 NodeList traceNodeList;
38 NodeList functionNodeList;
39 NodeList expressionNodeList;
40 NodeList tmpNodeList;
41 Node epochNode;
42 Node traceNode;
43 Node functionNode;
44 Node expressionNode;
45 Node tmpNode = null;
46 Element element;
47 Epoch epoch = null;
48 Function function = null;
49 Expression expression = null;
50 File xmlFile = new File(filePath);
51
52 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
53 .newInstance();
54 DocumentBuilder documentBuilder = documentBuilderFactory
55 .newDocumentBuilder();
56 Document document = documentBuilder.parse(xmlFile);
57 document.getDocumentElement().normalize();
58
59 /* Setting Bug Attributes */
60 element = document.getDocumentElement(); /*
61 * This should be the crash
62 * node
63 */
64 bug.setCategory(element.getAttribute("category"));
65 bug.setFileName(element.getAttribute("file"));
66 bug.setFunctionName(element.getAttribute("function"));
67 bug.setLineNo(Integer.parseInt(element.getAttribute("line")));
68
69 /* History is consisting of a list of epoch nodes */
70 epochNodeList = document.getElementsByTagName("epoch");
71 //printAllNodes(epochNodeList);
72 for (int i = 0; i < epochNodeList.getLength(); i++) {
73 epochNode = epochNodeList.item(i);
74 if (epochNode.getNodeType() == Node.ELEMENT_NODE) {
75 epoch = new Epoch();
76 bug.insertEpoch(epoch);
77 epoch.setEpochStep(Integer.parseInt(epochNode
78 .getAttributes().getNamedItem("step")
79 .getNodeValue()));
80
81 /* Get the list of trace nodes for this epoch node */
82 traceNodeList = epochNode.getChildNodes();
83 for (int j = 0; j < traceNodeList.getLength(); j++) {
84 /* Get the list of function nodes for this trace node */
85 traceNode = traceNodeList.item(j);
86 if (traceNode.getNodeType() == Node.ELEMENT_NODE) {
87 functionNodeList = traceNode.getChildNodes();
88 for (int k = 0; k < functionNodeList.getLength(); k++) {
89 functionNode = functionNodeList.item(k);
90 if (functionNode.getNodeType() == Node.ELEMENT_NODE) {
91 function = new Function();
92 epoch.insertFunction(function);
93 function.setFunctionName(functionNode
94 .getAttributes()
95 .getNamedItem("name")
96 .getNodeValue());
97 function.setLineNo(Integer
98 .parseInt(functionNode
99 .getAttributes()
100 .getNamedItem("line")
101 .getNodeValue()));
102 function.setFileName(functionNode
103 .getAttributes()
104 .getNamedItem("file")
105 .getNodeValue());
106
107 /*
108 * Get the list of expression nodes for this
109 * function
110 */
111 tmpNodeList = functionNode.getChildNodes();
112 for (int t = 0; t < tmpNodeList.getLength(); t++) { // skipping the
113 // unnecessary
114 // node
115 // named
116 // <expressions></expressions>
117 tmpNode = tmpNodeList.item(t);
118 if (tmpNode.getNodeName().equals("expressions"))
119 break;
120 }
121 expressionNodeList = tmpNode.getChildNodes();
122 for (int l = 0; l < expressionNodeList
123 .getLength(); l++) {
124 expressionNode = expressionNodeList
125 .item(l);
126 if (expressionNode.getNodeType() == Node.ELEMENT_NODE) {
127 expression = new Expression();
128 function.insertExpression(expression);
129 expression.setName(expressionNode
130 .getAttributes()
131 .getNamedItem("name")
132 .getNodeValue());
133 expression.setValue(expressionNode
134 .getTextContent());
135 }
136 }
137 } // end if functionNode
138 } // end for functionNodeList
139 } // end if traceNode
140 } // end for traceNodeList
141 } // end if epochNode
142 } // end for epochNodeList
143 } catch (Exception e) {
144 System.err.println("Fatal error: unable to parse XML file. Entomologist will exit now.");
145 e.printStackTrace();
146 System.exit(1);
147 }
148 return bug;
149 }
150
151 public static void printBug(Bug bug) {
152 Epoch epoch;
153 Function function;
154 Expression expression;
155 System.out.println("Bug:");
156 System.out.println("---------");
157 System.out.println("Category: " + bug.getCategory());
158 System.out.println("File Name: " + bug.getFileName());
159 System.out.println("Function Name: " + bug.getFunctionName());
160 System.out.println("Line Number: " + bug.getLineNo());
161 System.out.println("------------------------------------------------------");
162 for (int i = 0; i < bug.getEpochNum(); i++) {
163 epoch = bug.getEpoch(i);
164 System.out.println("Epoch Step: " + epoch.getEpochStep());
165 System.out.println("---------------");
166 for (int j = 0; j < epoch.getFunctionNum(); j++) {
167 function = epoch.getFunction(j);
168 System.out.println("Function: " + function.getFunctionName() + " file: " + function.getFileName() + " Lineno." + function.getLineNo());
169 System.out.println("-----------------------------------------------------");
170 for (int k = 0; k < function.getExpressionNum(); k++) {
171 expression = function.getExpression(k);
172 System.out.println(expression.getName() + " = " + expression.getValue());
173 }
174 System.out.println("");
175 }
176 System.out.println("");
177 }
178 }
179
180
181
182 // This method is used for debugging
183 /*
184 private static void printAllNodes(NodeList nodeList) {
185 NodeList childNodes;
186 for (int i = 0; i < nodeList.getLength(); i++) {
187 if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE) {
188 System.out.println(nodeList.item(i).getNodeName() + " type ="
189 + nodeList.item(i).getNodeType());
190 childNodes = nodeList.item(i).getChildNodes();
191 printAllNodes(childNodes);
192 }
193 }
194 }
195 */
196}
diff --git a/entomologist/src/org/monkey/comparator/testing/ComparatorTest.java b/entomologist/src/org/monkey/comparator/testing/ComparatorTest.java
new file mode 100644
index 0000000..5906fd3
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/ComparatorTest.java
@@ -0,0 +1,111 @@
1package org.monkey.comparator.testing;
2
3import static org.junit.Assert.*;
4
5import org.junit.Test;
6import org.monkey.comparator.MonkeyComparator;
7import org.monkey.comparator.bo.Bug;
8import org.monkey.comparator.bo.XMLParser;
9
10public class ComparatorTest {
11
12 @Test
13 public void testTotalSimilarity() {
14 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey.xml");
15 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey.xml");
16 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
17 assertEquals(100.0, similarityPercentage, 0);
18 System.out.println("score = " + similarityPercentage);
19 }
20
21 @Test
22 public void testSameStackDifferentFunctionNames() {
23 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey.xml");
24 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_fname.xml");
25
26 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
27 assertEquals(99.58333333333333, similarityPercentage, 0);
28 System.out.println("score = " + similarityPercentage);
29 }
30
31 @Test
32 public void testCommonAndDifferentExpressions() {
33 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey.xml");
34 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_common_and_different_exp.xml");
35
36 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
37 assertEquals(93.33333333333333, similarityPercentage, 0);
38 System.out.println("score = " + similarityPercentage);
39 }
40
41 @Test
42 public void testSlightlyDifferentStackTraces() {
43 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey.xml");
44 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_trace.xml");
45
46 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
47 assertEquals(88.8888888888889, similarityPercentage, 0);
48 System.out.println("score = " + similarityPercentage);
49 }
50
51 @Test
52 public void testNpeAndNpeExpressionsModified() {
53 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/npe.xml");
54 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/npe_expressions_modified.xml");
55
56 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
57 assertEquals(89.25, similarityPercentage, 0);
58 System.out.println("score = " + similarityPercentage);
59 }
60
61 @Test
62 public void testNpeAndNpeExpressionsAndStackModified() {
63 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/npe.xml");
64 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/npe_expressions_and_stack_modified.xml");
65
66 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
67 assertEquals(80.76282051282053, similarityPercentage, 0);
68 System.out.println("score = " + similarityPercentage);
69 }
70
71
72 @Test
73 public void testNpeAndDivisionByZero() {
74 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/npe.xml");
75 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/npe_divzero.xml");
76
77 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
78 System.out.println("score = " + similarityPercentage);
79 assertEquals(32.958333333333336, similarityPercentage, 0);
80 }
81
82 @Test
83 public void testIdenticalHistory() {
84 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_trace.xml");
85 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_trace.xml");
86
87 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
88 System.out.println("score = " + similarityPercentage);
89 assertEquals(100.0, similarityPercentage, 0);
90 }
91
92 @Test
93 public void testDifferentHistory() {
94 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_trace.xml");
95 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_history.xml");
96
97 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
98 System.out.println("score = " + similarityPercentage);
99 assertEquals(94.44444444444446, similarityPercentage, 0);
100 }
101
102 @Test
103 public void testDifferentAndLongerHistory() {
104 Bug bugA = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_trace.xml");
105 Bug bugB = XMLParser.parse("src/org/monkey/comparator/testing/refs/monkey_different_and_longer_history.xml");
106
107 double similarityPercentage = MonkeyComparator.compareBugs(bugA, bugB, "comparator.properties");
108 System.out.println("score = " + similarityPercentage);
109 assertEquals(94.44444444444446, similarityPercentage, 0);
110 }
111}
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/monkey.xml b/entomologist/src/org/monkey/comparator/testing/refs/monkey.xml
new file mode 100644
index 0000000..f484a32
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/monkey.xml
@@ -0,0 +1,45 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history>
4<epoch step="0" >
5<trace>
6<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
7<expressions>
8<expression name="crashStruct" >NULL</expression>
9<expression name="x" >5</expression>
10<expression name="y" >6</expression>
11<expression name="s" >Hello</expression>
12</expressions>
13</function>
14<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
15<expressions>
16<expression name="a" >3</expression>
17<expression name="b" >7</expression>
18<expression name="c" >9</expression>
19<expression name="d" >112</expression>
20</expressions>
21</function>
22</trace>
23</epoch>
24<epoch step="1" >
25<trace>
26<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
27<expressions>
28<expression name="crashStruct" >NULL</expression>
29<expression name="x" >5</expression>
30<expression name="y" >6</expression>
31<expression name="s" >Hello</expression>
32</expressions>
33</function>
34<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
35<expressions>
36<expression name="a" >3</expression>
37<expression name="b" >7</expression>
38<expression name="c" >9</expression>
39<expression name="d" >112</expression>
40</expressions>
41</function>
42</trace>
43</epoch>
44</history>
45</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/monkey_common_and_different_exp.xml b/entomologist/src/org/monkey/comparator/testing/refs/monkey_common_and_different_exp.xml
new file mode 100644
index 0000000..9b69ef2
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/monkey_common_and_different_exp.xml
@@ -0,0 +1,47 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history>
4<epoch step="0" >
5<trace>
6<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
7<expressions>
8<expression name="crashStruct" >NULL</expression>
9<expression name="x" >5</expression>
10<expression name="p" >10</expression>
11<expression name="y" >6</expression>
12<expression name="ssss" >Hello</expression>
13</expressions>
14</function>
15<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
16<expressions>
17<expression name="a" >3</expression>
18<expression name="b" >7</expression>
19<expression name="c" >9</expression>
20<expression name="d" >112</expression>
21</expressions>
22</function>
23</trace>
24</epoch>
25<epoch step="1" >
26<trace>
27<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
28<expressions>
29<expression name="crashStruct" >NULL</expression>
30<expression name="x" >5</expression>
31<expression name="p" >10</expression>
32<expression name="y" >6</expression>
33<expression name="ssss" >Hello</expression>
34</expressions>
35</function>
36<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
37<expressions>
38<expression name="a" >3</expression>
39<expression name="b" >7</expression>
40<expression name="c" >9</expression>
41<expression name="d" >112</expression>
42</expressions>
43</function>
44</trace>
45</epoch>
46</history>
47</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_and_longer_history.xml b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_and_longer_history.xml
new file mode 100644
index 0000000..2a2edde
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_and_longer_history.xml
@@ -0,0 +1,114 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history>
4<epoch step="0" >
5<trace>
6<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
7<expressions>
8<expression name="crashStruct" >NULL</expression>
9<expression name="x" >5</expression>
10<expression name="y" >6</expression>
11<expression name="s" >Hello</expression>
12</expressions>
13</function>
14<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
15<expressions>
16<expression name="alpha" >1</expression>
17<expression name="beta" >2</expression>
18<expression name="gamma" >7</expression>
19<expression name="delta" >hurray</expression>
20</expressions>
21</function>
22<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
23<expressions>
24<expression name="a" >3</expression>
25<expression name="b" >7</expression>
26<expression name="c" >9</expression>
27<expression name="d" >112</expression>
28</expressions>
29</function>
30</trace>
31</epoch>
32<epoch step="1" >
33<trace>
34<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
35<expressions>
36<expression name="crashStruct" >NULL</expression>
37<expression name="x" >5</expression>
38<expression name="y" >6</expression>
39<expression name="s" >Hello</expression>
40</expressions>
41</function>
42<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
43<expressions>
44<expression name="alpha" >1</expression>
45<expression name="beta" >2</expression>
46<expression name="gamma" >7</expression>
47<expression name="delta" >hurray</expression>
48</expressions>
49</function>
50<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
51<expressions>
52<expression name="i" >3</expression>
53<expression name="j" >7</expression>
54<expression name="k" >9</expression>
55</expressions>
56</function>
57</trace>
58</epoch>
59<epoch step="2" >
60<trace>
61<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
62<expressions>
63<expression name="crashStruct" >NULL</expression>
64<expression name="x" >5</expression>
65<expression name="y" >6</expression>
66<expression name="s" >Hello</expression>
67</expressions>
68</function>
69<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
70<expressions>
71<expression name="alpha" >1</expression>
72<expression name="beta" >2</expression>
73<expression name="gamma" >7</expression>
74<expression name="delta" >hurray</expression>
75</expressions>
76</function>
77<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
78<expressions>
79<expression name="i" >3</expression>
80<expression name="j" >7</expression>
81<expression name="k" >9</expression>
82</expressions>
83</function>
84</trace>
85</epoch>
86<epoch step="3" >
87<trace>
88<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
89<expressions>
90<expression name="crashStruct" >NULL</expression>
91<expression name="x" >5</expression>
92<expression name="y" >6</expression>
93<expression name="s" >Hello</expression>
94</expressions>
95</function>
96<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
97<expressions>
98<expression name="alpha" >1</expression>
99<expression name="beta" >2</expression>
100<expression name="gamma" >7</expression>
101<expression name="delta" >hurray</expression>
102</expressions>
103</function>
104<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
105<expressions>
106<expression name="i" >3</expression>
107<expression name="j" >7</expression>
108<expression name="k" >9</expression>
109</expressions>
110</function>
111</trace>
112</epoch>
113</history>
114</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_fname.xml b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_fname.xml
new file mode 100644
index 0000000..4bc9adb
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_fname.xml
@@ -0,0 +1,45 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history>
4<epoch step="0" >
5<trace>
6<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
7<expressions>
8<expression name="crashStruct" >NULL</expression>
9<expression name="x" >5</expression>
10<expression name="y" >6</expression>
11<expression name="s" >Hello</expression>
12</expressions>
13</function>
14<function name="theOtherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
15<expressions>
16<expression name="a" >3</expression>
17<expression name="b" >7</expression>
18<expression name="c" >9</expression>
19<expression name="d" >112</expression>
20</expressions>
21</function>
22</trace>
23</epoch>
24<epoch step="1" >
25<trace>
26<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
27<expressions>
28<expression name="crashStruct" >NULL</expression>
29<expression name="x" >5</expression>
30<expression name="y" >6</expression>
31<expression name="s" >Hello</expression>
32</expressions>
33</function>
34<function name="theOtherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
35<expressions>
36<expression name="a" >3</expression>
37<expression name="b" >7</expression>
38<expression name="c" >9</expression>
39<expression name="d" >112</expression>
40</expressions>
41</function>
42</trace>
43</epoch>
44</history>
45</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_history.xml b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_history.xml
new file mode 100644
index 0000000..7fc9ac0
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_history.xml
@@ -0,0 +1,60 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history>
4<epoch step="0" >
5<trace>
6<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
7<expressions>
8<expression name="crashStruct" >NULL</expression>
9<expression name="x" >5</expression>
10<expression name="y" >6</expression>
11<expression name="s" >Hello</expression>
12</expressions>
13</function>
14<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
15<expressions>
16<expression name="alpha" >1</expression>
17<expression name="beta" >2</expression>
18<expression name="gamma" >7</expression>
19<expression name="delta" >hurray</expression>
20</expressions>
21</function>
22<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
23<expressions>
24<expression name="a" >3</expression>
25<expression name="b" >7</expression>
26<expression name="c" >9</expression>
27<expression name="d" >112</expression>
28</expressions>
29</function>
30</trace>
31</epoch>
32<epoch step="1" >
33<trace>
34<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
35<expressions>
36<expression name="crashStruct" >NULL</expression>
37<expression name="x" >5</expression>
38<expression name="y" >6</expression>
39<expression name="s" >Hello</expression>
40</expressions>
41</function>
42<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
43<expressions>
44<expression name="alpha" >1</expression>
45<expression name="beta" >2</expression>
46<expression name="gamma" >7</expression>
47<expression name="delta" >hurray</expression>
48</expressions>
49</function>
50<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
51<expressions>
52<expression name="i" >3</expression>
53<expression name="j" >7</expression>
54<expression name="k" >9</expression>
55</expressions>
56</function>
57</trace>
58</epoch>
59</history>
60</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_trace.xml b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_trace.xml
new file mode 100644
index 0000000..200364c
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/monkey_different_trace.xml
@@ -0,0 +1,61 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history>
4<epoch step="0" >
5<trace>
6<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
7<expressions>
8<expression name="crashStruct" >NULL</expression>
9<expression name="x" >5</expression>
10<expression name="y" >6</expression>
11<expression name="s" >Hello</expression>
12</expressions>
13</function>
14<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
15<expressions>
16<expression name="alpha" >1</expression>
17<expression name="beta" >2</expression>
18<expression name="gamma" >7</expression>
19<expression name="delta" >hurray</expression>
20</expressions>
21</function>
22<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
23<expressions>
24<expression name="a" >3</expression>
25<expression name="b" >7</expression>
26<expression name="c" >9</expression>
27<expression name="d" >112</expression>
28</expressions>
29</function>
30</trace>
31</epoch>
32<epoch step="1" >
33<trace>
34<function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
35<expressions>
36<expression name="crashStruct" >NULL</expression>
37<expression name="x" >5</expression>
38<expression name="y" >6</expression>
39<expression name="s" >Hello</expression>
40</expressions>
41</function>
42<function name="intermediateFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
43<expressions>
44<expression name="alpha" >1</expression>
45<expression name="beta" >2</expression>
46<expression name="gamma" >7</expression>
47<expression name="delta" >hurray</expression>
48</expressions>
49</function>
50<function name="anotherCrashFunction" line="3" file="bug_null_pointer_exception.c" depth="1" >
51<expressions>
52<expression name="a" >3</expression>
53<expression name="b" >7</expression>
54<expression name="c" >9</expression>
55<expression name="d" >112</expression>
56</expressions>
57</function>
58</trace>
59</epoch>
60</history>
61</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/npe.xml b/entomologist/src/org/monkey/comparator/testing/refs/npe.xml
new file mode 100644
index 0000000..a5ae517
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/npe.xml
@@ -0,0 +1,29 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue=&quot;hello!&quot;" >
6Not Evaluated</expression>
7<expression name="crashStruct-&gt;crashValue" >
8Not Evaluated</expression>
9<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
10Not Evaluated</expression>
11<expression name="NULL" >
12Not Evaluated</expression>
13<expression name="crashStruct" >
140x0</expression>
15</expressions>
16</function>
17<function name="main" line="19" file="bug_null_pointer_exception.c" depth="1" >
18<expressions><expression name="crashFunction()" >
19Not Evaluated</expression>
20<expression name="argv" >
21Not Evaluated</expression>
22<expression name="argc" >
23Not Evaluated</expression>
24</expressions>
25</function>
26</trace>
27</epoch>
28</history>
29</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/npe_divzero.xml b/entomologist/src/org/monkey/comparator/testing/refs/npe_divzero.xml
new file mode 100644
index 0000000..7af7cfc
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/npe_divzero.xml
@@ -0,0 +1,43 @@
1<?xml version="1.0"?>
2<crash category="Division By Zero" function="crashFunction" line="21" file="bug_null_pointer_exception.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="21" file="bug_null_pointer_exception.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue" >
6Not Evaluated</expression>
7<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
8Not Evaluated</expression>
9<expression name="printf(&quot;result = %d\n&quot;,result)" >
10Not Evaluated</expression>
11<expression name="result/k" >
12Not Evaluated</expression>
13<expression name="i&lt;5" >
141</expression>
15<expression name="i" >
161</expression>
17<expression name="printf(&quot;I am alive!\n&quot;)" >
18Not Evaluated</expression>
19<expression name="result" >
20-10</expression>
21<expression name="-1" >
22-1</expression>
23<expression name="k" >
240</expression>
25<expression name="NULL" >
26Not Evaluated</expression>
27<expression name="crashStruct" >
280x0</expression>
29</expressions>
30</function>
31<function name="main" line="30" file="bug_null_pointer_exception.c" depth="1" >
32<expressions><expression name="crashFunction()" >
33Not Evaluated</expression>
34<expression name="argv" >
35Not Evaluated</expression>
36<expression name="argc" >
37Not Evaluated</expression>
38</expressions>
39</function>
40</trace>
41</epoch>
42</history>
43</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_and_stack_modified.xml b/entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_and_stack_modified.xml
new file mode 100644
index 0000000..6082988
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_and_stack_modified.xml
@@ -0,0 +1,42 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="20" file="bug_null_pointer_exception.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="20" file="bug_null_pointer_exception_modified.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue=&quot;hello!&quot;" >
6Not Evaluated</expression>
7<expression name="crashStruct-&gt;crashValue" >
8Not Evaluated</expression>
9<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
10Not Evaluated</expression>
11<expression name="NULL" >
12Not Evaluated</expression>
13<expression name="crashStruct" >
140x0</expression>
15<expression name="a+b" >
168</expression>
17<expression name="c" >
188</expression>
19<expression name="b" >
205</expression>
21<expression name="a" >
223</expression>
23</expressions>
24</function>
25<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
26<expressions><expression name="crashFunction()" >
27Not Evaluated</expression>
28</expressions>
29</function>
30<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
31<expressions><expression name="intermediateFunction()" >
32Not Evaluated</expression>
33<expression name="argv" >
34Not Evaluated</expression>
35<expression name="argc" >
36Not Evaluated</expression>
37</expressions>
38</function>
39</trace>
40</epoch>
41</history>
42</crash>
diff --git a/entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_modified.xml b/entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_modified.xml
new file mode 100644
index 0000000..ad2ac79
--- /dev/null
+++ b/entomologist/src/org/monkey/comparator/testing/refs/npe_expressions_modified.xml
@@ -0,0 +1,37 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="20" file="bug_null_pointer_exception.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="20" file="bug_null_pointer_exception.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue=&quot;hello!&quot;" >
6Not Evaluated</expression>
7<expression name="crashStruct-&gt;crashValue" >
8Not Evaluated</expression>
9<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
10Not Evaluated</expression>
11<expression name="NULL" >
12Not Evaluated</expression>
13<expression name="crashStruct" >
140x0</expression>
15<expression name="a+b" >
168</expression>
17<expression name="c" >
188</expression>
19<expression name="b" >
205</expression>
21<expression name="a" >
223</expression>
23</expressions>
24</function>
25<function name="main" line="25" file="bug_null_pointer_exception.c" depth="1" >
26<expressions><expression name="crashFunction()" >
27Not Evaluated</expression>
28<expression name="argv" >
29Not Evaluated</expression>
30<expression name="argc" >
31Not Evaluated</expression>
32</expressions>
33</function>
34</trace>
35</epoch>
36</history>
37</crash>
diff --git a/monkey_build_script b/monkey_build_script
new file mode 100644
index 0000000..dad9937
--- /dev/null
+++ b/monkey_build_script
@@ -0,0 +1,16 @@
1#!/bin/sh
2
3echo "################## UNINSTALLING MONKEY ##################"
4sudo make uninstall
5echo "################## CLEANING WORKING DIRECTORY ###########"
6sudo make clean
7sudo make distclean
8echo "################## BOOTSTRAPPING ########################"
9./bootstrap
10echo "################## CONFIGURING MONKEY ###################"
11CFLAGS="-g -O0" ./configure
12echo "################## BUILDING MONKEY ######################"
13make
14echo "################## INSTALLING MONKEY ####################"
15sudo make install
16
diff --git a/pathologist/ABOUT-NLS b/pathologist/ABOUT-NLS
new file mode 100644
index 0000000..83bc72e
--- /dev/null
+++ b/pathologist/ABOUT-NLS
@@ -0,0 +1,1068 @@
11 Notes on the Free Translation Project
2***************************************
3
4Free software is going international! The Free Translation Project is
5a way to get maintainers of free software, translators, and users all
6together, so that free software will gradually become able to speak many
7languages. A few packages already provide translations for their
8messages.
9
10 If you found this `ABOUT-NLS' file inside a distribution, you may
11assume that the distributed package does use GNU `gettext' internally,
12itself available at your nearest GNU archive site. But you do _not_
13need to install GNU `gettext' prior to configuring, installing or using
14this package with messages translated.
15
16 Installers will find here some useful hints. These notes also
17explain how users should proceed for getting the programs to use the
18available translations. They tell how people wanting to contribute and
19work on translations can contact the appropriate team.
20
21 When reporting bugs in the `intl/' directory or bugs which may be
22related to internationalization, you should tell about the version of
23`gettext' which is used. The information can be found in the
24`intl/VERSION' file, in internationalized packages.
25
261.1 Quick configuration advice
27==============================
28
29If you want to exploit the full power of internationalization, you
30should configure it using
31
32 ./configure --with-included-gettext
33
34to force usage of internationalizing routines provided within this
35package, despite the existence of internationalizing capabilities in the
36operating system where this package is being installed. So far, only
37the `gettext' implementation in the GNU C library version 2 provides as
38many features (such as locale alias, message inheritance, automatic
39charset conversion or plural form handling) as the implementation here.
40It is also not possible to offer this additional functionality on top
41of a `catgets' implementation. Future versions of GNU `gettext' will
42very likely convey even more functionality. So it might be a good idea
43to change to GNU `gettext' as soon as possible.
44
45 So you need _not_ provide this option if you are using GNU libc 2 or
46you have installed a recent copy of the GNU gettext package with the
47included `libintl'.
48
491.2 INSTALL Matters
50===================
51
52Some packages are "localizable" when properly installed; the programs
53they contain can be made to speak your own native language. Most such
54packages use GNU `gettext'. Other packages have their own ways to
55internationalization, predating GNU `gettext'.
56
57 By default, this package will be installed to allow translation of
58messages. It will automatically detect whether the system already
59provides the GNU `gettext' functions. If not, the included GNU
60`gettext' library will be used. This library is wholly contained
61within this package, usually in the `intl/' subdirectory, so prior
62installation of the GNU `gettext' package is _not_ required.
63Installers may use special options at configuration time for changing
64the default behaviour. The commands:
65
66 ./configure --with-included-gettext
67 ./configure --disable-nls
68
69will, respectively, bypass any pre-existing `gettext' to use the
70internationalizing routines provided within this package, or else,
71_totally_ disable translation of messages.
72
73 When you already have GNU `gettext' installed on your system and run
74configure without an option for your new package, `configure' will
75probably detect the previously built and installed `libintl.a' file and
76will decide to use this. This might not be desirable. You should use
77the more recent version of the GNU `gettext' library. I.e. if the file
78`intl/VERSION' shows that the library which comes with this package is
79more recent, you should use
80
81 ./configure --with-included-gettext
82
83to prevent auto-detection.
84
85 The configuration process will not test for the `catgets' function
86and therefore it will not be used. The reason is that even an
87emulation of `gettext' on top of `catgets' could not provide all the
88extensions of the GNU `gettext' library.
89
90 Internationalized packages usually have many `po/LL.po' files, where
91LL gives an ISO 639 two-letter code identifying the language. Unless
92translations have been forbidden at `configure' time by using the
93`--disable-nls' switch, all available translations are installed
94together with the package. However, the environment variable `LINGUAS'
95may be set, prior to configuration, to limit the installed set.
96`LINGUAS' should then contain a space separated list of two-letter
97codes, stating which languages are allowed.
98
991.3 Using This Package
100======================
101
102As a user, if your language has been installed for this package, you
103only have to set the `LANG' environment variable to the appropriate
104`LL_CC' combination. If you happen to have the `LC_ALL' or some other
105`LC_xxx' environment variables set, you should unset them before
106setting `LANG', otherwise the setting of `LANG' will not have the
107desired effect. Here `LL' is an ISO 639 two-letter language code, and
108`CC' is an ISO 3166 two-letter country code. For example, let's
109suppose that you speak German and live in Germany. At the shell
110prompt, merely execute `setenv LANG de_DE' (in `csh'),
111`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
112This can be done from your `.login' or `.profile' file, once and for
113all.
114
115 You might think that the country code specification is redundant.
116But in fact, some languages have dialects in different countries. For
117example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
118country code serves to distinguish the dialects.
119
120 The locale naming convention of `LL_CC', with `LL' denoting the
121language and `CC' denoting the country, is the one use on systems based
122on GNU libc. On other systems, some variations of this scheme are
123used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
124locales supported by your system for your language by running the
125command `locale -a | grep '^LL''.
126
127 Not all programs have translations for all languages. By default, an
128English message is shown in place of a nonexistent translation. If you
129understand other languages, you can set up a priority list of languages.
130This is done through a different environment variable, called
131`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
132for the purpose of message handling, but you still need to have `LANG'
133set to the primary language; this is required by other parts of the
134system libraries. For example, some Swedish users who would rather
135read translations in German than English for when Swedish is not
136available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
137
138 Special advice for Norwegian users: The language code for Norwegian
139bokma*l changed from `no' to `nb' recently (in 2003). During the
140transition period, while some message catalogs for this language are
141installed under `nb' and some older ones under `no', it's recommended
142for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and
143older translations are used.
144
145 In the `LANGUAGE' environment variable, but not in the `LANG'
146environment variable, `LL_CC' combinations can be abbreviated as `LL'
147to denote the language's main dialect. For example, `de' is equivalent
148to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
149(Portuguese as spoken in Portugal) in this context.
150
1511.4 Translating Teams
152=====================
153
154For the Free Translation Project to be a success, we need interested
155people who like their own language and write it well, and who are also
156able to synergize with other translators speaking the same language.
157Each translation team has its own mailing list. The up-to-date list of
158teams can be found at the Free Translation Project's homepage,
159`http://translationproject.org/', in the "Teams" area.
160
161 If you'd like to volunteer to _work_ at translating messages, you
162should become a member of the translating team for your own language.
163The subscribing address is _not_ the same as the list itself, it has
164`-request' appended. For example, speakers of Swedish can send a
165message to `sv-request@li.org', having this message body:
166
167 subscribe
168
169 Keep in mind that team members are expected to participate
170_actively_ in translations, or at solving translational difficulties,
171rather than merely lurking around. If your team does not exist yet and
172you want to start one, or if you are unsure about what to do or how to
173get started, please write to `coordinator@translationproject.org' to
174reach the coordinator for all translator teams.
175
176 The English team is special. It works at improving and uniformizing
177the terminology in use. Proven linguistic skills are praised more than
178programming skills, here.
179
1801.5 Available Packages
181======================
182
183Languages are not equally supported in all packages. The following
184matrix shows the current state of internationalization, as of November
1852007. The matrix shows, in regard of each package, for which languages
186PO files have been submitted to translation coordination, with a
187translation percentage of at least 50%.
188
189 Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo
190 +----------------------------------------------------+
191 Compendium | [] [] [] [] |
192 a2ps | [] [] [] [] [] |
193 aegis | () |
194 ant-phone | () |
195 anubis | [] |
196 ap-utils | |
197 aspell | [] [] [] [] [] |
198 bash | [] |
199 bfd | |
200 bibshelf | [] |
201 binutils | |
202 bison | [] [] |
203 bison-runtime | [] |
204 bluez-pin | [] [] [] [] [] |
205 cflow | [] |
206 clisp | [] [] [] |
207 console-tools | [] [] |
208 coreutils | [] [] [] [] |
209 cpio | |
210 cpplib | [] [] [] |
211 cryptonit | [] |
212 dialog | |
213 diffutils | [] [] [] [] [] [] |
214 doodle | [] |
215 e2fsprogs | [] [] |
216 enscript | [] [] [] [] |
217 fetchmail | [] [] () [] [] |
218 findutils | [] |
219 findutils_stable | [] [] [] |
220 flex | [] [] [] |
221 fslint | |
222 gas | |
223 gawk | [] [] [] |
224 gcal | [] |
225 gcc | [] |
226 gettext-examples | [] [] [] [] [] |
227 gettext-runtime | [] [] [] [] [] |
228 gettext-tools | [] [] |
229 gip | [] |
230 gliv | [] [] |
231 glunarclock | [] |
232 gmult | [] [] |
233 gnubiff | () |
234 gnucash | [] [] () () [] |
235 gnuedu | |
236 gnulib | [] |
237 gnunet | |
238 gnunet-gtk | |
239 gnutls | [] |
240 gpe-aerial | [] [] |
241 gpe-beam | [] [] |
242 gpe-calendar | |
243 gpe-clock | [] [] |
244 gpe-conf | [] [] |
245 gpe-contacts | |
246 gpe-edit | [] |
247 gpe-filemanager | |
248 gpe-go | [] |
249 gpe-login | [] [] |
250 gpe-ownerinfo | [] [] |
251 gpe-package | |
252 gpe-sketchbook | [] [] |
253 gpe-su | [] [] |
254 gpe-taskmanager | [] [] |
255 gpe-timesheet | [] |
256 gpe-today | [] [] |
257 gpe-todo | |
258 gphoto2 | [] [] [] [] |
259 gprof | [] [] |
260 gpsdrive | |
261 gramadoir | [] [] |
262 grep | [] [] |
263 gretl | () |
264 gsasl | |
265 gss | |
266 gst-plugins-bad | [] [] |
267 gst-plugins-base | [] [] |
268 gst-plugins-good | [] [] [] |
269 gst-plugins-ugly | [] [] |
270 gstreamer | [] [] [] [] [] [] [] |
271 gtick | () |
272 gtkam | [] [] [] [] |
273 gtkorphan | [] [] |
274 gtkspell | [] [] [] [] |
275 gutenprint | [] |
276 hello | [] [] [] [] [] |
277 herrie | [] |
278 hylafax | |
279 idutils | [] [] |
280 indent | [] [] [] [] |
281 iso_15924 | |
282 iso_3166 | [] [] [] [] [] [] [] [] [] [] [] |
283 iso_3166_2 | |
284 iso_4217 | [] [] [] |
285 iso_639 | [] [] [] [] |
286 jpilot | [] |
287 jtag | |
288 jwhois | |
289 kbd | [] [] [] [] |
290 keytouch | [] [] |
291 keytouch-editor | [] |
292 keytouch-keyboa... | [] |
293 latrine | () |
294 ld | [] |
295 leafpad | [] [] [] [] [] |
296 libc | [] [] [] [] |
297 libexif | [] |
298 libextractor | [] |
299 libgpewidget | [] [] [] |
300 libgpg-error | [] |
301 libgphoto2 | [] [] |
302 libgphoto2_port | [] [] |
303 libgsasl | |
304 libiconv | [] [] |
305 libidn | [] [] [] |
306 lifelines | [] () |
307 lilypond | [] |
308 lingoteach | |
309 lprng | |
310 lynx | [] [] [] [] |
311 m4 | [] [] [] [] |
312 mailfromd | |
313 mailutils | [] |
314 make | [] [] |
315 man-db | [] [] [] |
316 minicom | [] [] [] |
317 nano | [] [] [] |
318 opcodes | [] |
319 parted | [] [] |
320 pilot-qof | |
321 popt | [] [] [] |
322 psmisc | [] |
323 pwdutils | |
324 qof | |
325 radius | [] |
326 recode | [] [] [] [] [] [] |
327 rpm | [] |
328 screem | |
329 scrollkeeper | [] [] [] [] [] [] [] [] |
330 sed | [] [] [] |
331 shared-mime-info | [] [] [] [] () [] [] [] |
332 sharutils | [] [] [] [] [] [] |
333 shishi | |
334 skencil | [] () |
335 solfege | |
336 soundtracker | [] [] |
337 sp | [] |
338 system-tools-ba... | [] [] [] [] [] [] [] [] [] |
339 tar | [] [] |
340 texinfo | [] [] [] |
341 tin | () () |
342 tuxpaint | [] [] [] [] [] [] |
343 unicode-han-tra... | |
344 unicode-transla... | |
345 util-linux | [] [] [] [] |
346 util-linux-ng | [] [] [] [] |
347 vorbis-tools | [] |
348 wastesedge | () |
349 wdiff | [] [] [] [] |
350 wget | [] [] [] |
351 xchat | [] [] [] [] [] [] [] |
352 xkeyboard-config | [] |
353 xpad | [] [] [] |
354 +----------------------------------------------------+
355 af am ar az be bg bs ca cs cy da de el en en_GB eo
356 6 0 2 1 8 26 2 40 48 2 56 88 15 1 15 18
357
358 es et eu fa fi fr ga gl gu he hi hr hu id is it
359 +--------------------------------------------------+
360 Compendium | [] [] [] [] [] |
361 a2ps | [] [] [] () |
362 aegis | |
363 ant-phone | [] |
364 anubis | [] |
365 ap-utils | [] [] |
366 aspell | [] [] [] |
367 bash | [] |
368 bfd | [] [] |
369 bibshelf | [] [] [] |
370 binutils | [] [] [] |
371 bison | [] [] [] [] [] [] |
372 bison-runtime | [] [] [] [] [] |
373 bluez-pin | [] [] [] [] [] |
374 cflow | [] |
375 clisp | [] [] |
376 console-tools | |
377 coreutils | [] [] [] [] [] [] |
378 cpio | [] [] [] |
379 cpplib | [] [] |
380 cryptonit | [] |
381 dialog | [] [] [] |
382 diffutils | [] [] [] [] [] [] [] [] [] |
383 doodle | [] [] |
384 e2fsprogs | [] [] [] |
385 enscript | [] [] [] |
386 fetchmail | [] |
387 findutils | [] [] [] |
388 findutils_stable | [] [] [] [] |
389 flex | [] [] [] |
390 fslint | |
391 gas | [] [] |
392 gawk | [] [] [] [] () |
393 gcal | [] [] |
394 gcc | [] |
395 gettext-examples | [] [] [] [] [] [] [] |
396 gettext-runtime | [] [] [] [] [] [] |
397 gettext-tools | [] [] [] [] |
398 gip | [] [] [] [] |
399 gliv | () |
400 glunarclock | [] [] [] |
401 gmult | [] [] [] |
402 gnubiff | () () |
403 gnucash | () () () |
404 gnuedu | [] |
405 gnulib | [] [] [] |
406 gnunet | |
407 gnunet-gtk | |
408 gnutls | |
409 gpe-aerial | [] [] |
410 gpe-beam | [] [] |
411 gpe-calendar | |
412 gpe-clock | [] [] [] [] |
413 gpe-conf | [] |
414 gpe-contacts | [] [] |
415 gpe-edit | [] [] [] [] |
416 gpe-filemanager | [] |
417 gpe-go | [] [] [] |
418 gpe-login | [] [] [] |
419 gpe-ownerinfo | [] [] [] [] [] |
420 gpe-package | [] |
421 gpe-sketchbook | [] [] |
422 gpe-su | [] [] [] [] |
423 gpe-taskmanager | [] [] [] |
424 gpe-timesheet | [] [] [] [] |
425 gpe-today | [] [] [] [] |
426 gpe-todo | [] |
427 gphoto2 | [] [] [] [] [] |
428 gprof | [] [] [] [] [] |
429 gpsdrive | [] |
430 gramadoir | [] [] |
431 grep | [] [] [] |
432 gretl | [] [] [] () |
433 gsasl | [] [] |
434 gss | [] [] |
435 gst-plugins-bad | [] [] [] [] |
436 gst-plugins-base | [] [] [] [] |
437 gst-plugins-good | [] [] [] [] [] |
438 gst-plugins-ugly | [] [] [] [] |
439 gstreamer | [] [] [] |
440 gtick | [] [] [] |
441 gtkam | [] [] [] [] |
442 gtkorphan | [] [] |
443 gtkspell | [] [] [] [] [] [] [] |
444 gutenprint | [] |
445 hello | [] [] [] [] [] [] [] [] [] [] [] [] [] |
446 herrie | [] |
447 hylafax | |
448 idutils | [] [] [] [] [] |
449 indent | [] [] [] [] [] [] [] [] [] [] |
450 iso_15924 | [] |
451 iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] |
452 iso_3166_2 | [] |
453 iso_4217 | [] [] [] [] [] [] |
454 iso_639 | [] [] [] [] [] [] |
455 jpilot | [] [] |
456 jtag | [] |
457 jwhois | [] [] [] [] [] |
458 kbd | [] [] |
459 keytouch | [] [] [] |
460 keytouch-editor | [] |
461 keytouch-keyboa... | [] [] |
462 latrine | [] [] |
463 ld | [] [] [] [] |
464 leafpad | [] [] [] [] [] [] |
465 libc | [] [] [] [] [] |
466 libexif | [] |
467 libextractor | [] |
468 libgpewidget | [] [] [] [] [] |
469 libgpg-error | [] |
470 libgphoto2 | [] [] [] |
471 libgphoto2_port | [] [] |
472 libgsasl | [] [] |
473 libiconv | [] [] [] |
474 libidn | [] [] |
475 lifelines | () |
476 lilypond | [] [] [] |
477 lingoteach | [] [] [] |
478 lprng | |
479 lynx | [] [] [] |
480 m4 | [] [] [] [] |
481 mailfromd | |
482 mailutils | [] [] |
483 make | [] [] [] [] [] [] [] [] |
484 man-db | [] |
485 minicom | [] [] [] [] |
486 nano | [] [] [] [] [] [] [] |
487 opcodes | [] [] [] [] |
488 parted | [] [] [] |
489 pilot-qof | |
490 popt | [] [] [] [] |
491 psmisc | [] [] |
492 pwdutils | |
493 qof | [] |
494 radius | [] [] |
495 recode | [] [] [] [] [] [] [] [] |
496 rpm | [] [] |
497 screem | |
498 scrollkeeper | [] [] [] |
499 sed | [] [] [] [] [] |
500 shared-mime-info | [] [] [] [] [] [] |
501 sharutils | [] [] [] [] [] [] [] [] |
502 shishi | [] |
503 skencil | [] [] |
504 solfege | [] |
505 soundtracker | [] [] [] |
506 sp | [] |
507 system-tools-ba... | [] [] [] [] [] [] [] [] [] |
508 tar | [] [] [] [] [] |
509 texinfo | [] [] [] |
510 tin | [] () |
511 tuxpaint | [] [] |
512 unicode-han-tra... | |
513 unicode-transla... | [] [] |
514 util-linux | [] [] [] [] [] [] [] |
515 util-linux-ng | [] [] [] [] [] [] [] |
516 vorbis-tools | |
517 wastesedge | () |
518 wdiff | [] [] [] [] [] [] [] [] |
519 wget | [] [] [] [] [] [] [] [] |
520 xchat | [] [] [] [] [] [] [] |
521 xkeyboard-config | [] [] [] [] |
522 xpad | [] [] [] |
523 +--------------------------------------------------+
524 es et eu fa fi fr ga gl gu he hi hr hu id is it
525 85 22 14 2 48 101 61 12 2 8 2 6 53 29 1 52
526
527 ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn
528 +--------------------------------------------------+
529 Compendium | [] |
530 a2ps | () [] [] |
531 aegis | () |
532 ant-phone | [] |
533 anubis | [] [] [] |
534 ap-utils | [] |
535 aspell | [] [] |
536 bash | [] |
537 bfd | |
538 bibshelf | [] |
539 binutils | |
540 bison | [] [] [] |
541 bison-runtime | [] [] [] |
542 bluez-pin | [] [] [] |
543 cflow | |
544 clisp | [] |
545 console-tools | |
546 coreutils | [] |
547 cpio | [] |
548 cpplib | [] |
549 cryptonit | [] |
550 dialog | [] [] |
551 diffutils | [] [] [] |
552 doodle | |
553 e2fsprogs | [] |
554 enscript | [] |
555 fetchmail | [] [] |
556 findutils | [] |
557 findutils_stable | [] |
558 flex | [] [] |
559 fslint | |
560 gas | |
561 gawk | [] [] |
562 gcal | |
563 gcc | |
564 gettext-examples | [] [] [] |
565 gettext-runtime | [] [] [] |
566 gettext-tools | [] [] |
567 gip | [] [] |
568 gliv | [] |
569 glunarclock | [] [] |
570 gmult | [] [] [] |
571 gnubiff | |
572 gnucash | () () () |
573 gnuedu | |
574 gnulib | [] [] |
575 gnunet | |
576 gnunet-gtk | |
577 gnutls | [] |
578 gpe-aerial | [] |
579 gpe-beam | [] |
580 gpe-calendar | [] |
581 gpe-clock | [] [] [] |
582 gpe-conf | [] [] [] |
583 gpe-contacts | [] |
584 gpe-edit | [] [] [] |
585 gpe-filemanager | [] [] |
586 gpe-go | [] [] [] |
587 gpe-login | [] [] [] |
588 gpe-ownerinfo | [] [] |
589 gpe-package | [] [] |
590 gpe-sketchbook | [] [] |
591 gpe-su | [] [] [] |
592 gpe-taskmanager | [] [] [] [] |
593 gpe-timesheet | [] |
594 gpe-today | [] [] |
595 gpe-todo | [] |
596 gphoto2 | [] [] |
597 gprof | [] |
598 gpsdrive | [] |
599 gramadoir | () |
600 grep | [] [] |
601 gretl | |
602 gsasl | [] |
603 gss | |
604 gst-plugins-bad | [] |
605 gst-plugins-base | [] |
606 gst-plugins-good | [] |
607 gst-plugins-ugly | [] |
608 gstreamer | [] |
609 gtick | [] |
610 gtkam | [] [] |
611 gtkorphan | [] |
612 gtkspell | [] [] |
613 gutenprint | [] |
614 hello | [] [] [] [] [] [] [] |
615 herrie | [] |
616 hylafax | |
617 idutils | [] |
618 indent | [] [] |
619 iso_15924 | [] |
620 iso_3166 | [] [] [] [] [] [] [] [] |
621 iso_3166_2 | [] |
622 iso_4217 | [] [] [] |
623 iso_639 | [] [] [] [] |
624 jpilot | () () |
625 jtag | |
626 jwhois | [] |
627 kbd | [] |
628 keytouch | [] |
629 keytouch-editor | [] |
630 keytouch-keyboa... | |
631 latrine | [] |
632 ld | |
633 leafpad | [] [] |
634 libc | [] [] [] |
635 libexif | |
636 libextractor | |
637 libgpewidget | [] |
638 libgpg-error | |
639 libgphoto2 | [] |
640 libgphoto2_port | [] |
641 libgsasl | [] |
642 libiconv | [] |
643 libidn | [] [] |
644 lifelines | [] |
645 lilypond | [] |
646 lingoteach | [] |
647 lprng | |
648 lynx | [] [] |
649 m4 | [] [] |
650 mailfromd | |
651 mailutils | |
652 make | [] [] [] |
653 man-db | |
654 minicom | [] |
655 nano | [] [] [] |
656 opcodes | [] |
657 parted | [] [] |
658 pilot-qof | |
659 popt | [] [] [] |
660 psmisc | [] [] [] |
661 pwdutils | |
662 qof | |
663 radius | |
664 recode | [] |
665 rpm | [] [] |
666 screem | [] |
667 scrollkeeper | [] [] [] [] |
668 sed | [] [] |
669 shared-mime-info | [] [] [] [] [] [] [] |
670 sharutils | [] [] |
671 shishi | |
672 skencil | |
673 solfege | () () |
674 soundtracker | |
675 sp | () |
676 system-tools-ba... | [] [] [] [] |
677 tar | [] [] [] |
678 texinfo | [] [] |
679 tin | |
680 tuxpaint | () [] [] |
681 unicode-han-tra... | |
682 unicode-transla... | |
683 util-linux | [] [] |
684 util-linux-ng | [] [] |
685 vorbis-tools | |
686 wastesedge | [] |
687 wdiff | [] [] |
688 wget | [] [] |
689 xchat | [] [] [] [] |
690 xkeyboard-config | [] [] [] |
691 xpad | [] [] [] |
692 +--------------------------------------------------+
693 ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn
694 51 2 25 3 2 0 6 0 2 2 20 0 11 1 103 6
695
696 or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta
697 +--------------------------------------------------+
698 Compendium | [] [] [] [] [] |
699 a2ps | () [] [] [] [] [] [] |
700 aegis | () () |
701 ant-phone | [] [] |
702 anubis | [] [] [] |
703 ap-utils | () |
704 aspell | [] [] [] |
705 bash | [] [] |
706 bfd | |
707 bibshelf | [] |
708 binutils | [] [] |
709 bison | [] [] [] [] [] |
710 bison-runtime | [] [] [] [] [] |
711 bluez-pin | [] [] [] [] [] [] [] [] [] |
712 cflow | [] |
713 clisp | [] |
714 console-tools | [] |
715 coreutils | [] [] [] [] |
716 cpio | [] [] [] |
717 cpplib | [] |
718 cryptonit | [] [] |
719 dialog | [] |
720 diffutils | [] [] [] [] [] [] |
721 doodle | [] [] |
722 e2fsprogs | [] [] |
723 enscript | [] [] [] [] [] |
724 fetchmail | [] [] [] |
725 findutils | [] [] [] |
726 findutils_stable | [] [] [] [] [] [] |
727 flex | [] [] [] [] [] |
728 fslint | [] |
729 gas | |
730 gawk | [] [] [] [] |
731 gcal | [] |
732 gcc | [] [] |
733 gettext-examples | [] [] [] [] [] [] [] [] |
734 gettext-runtime | [] [] [] [] [] [] [] [] |
735 gettext-tools | [] [] [] [] [] [] [] |
736 gip | [] [] [] [] |
737 gliv | [] [] [] [] [] [] |
738 glunarclock | [] [] [] [] [] [] |
739 gmult | [] [] [] [] |
740 gnubiff | () [] |
741 gnucash | () [] |
742 gnuedu | |
743 gnulib | [] [] [] |
744 gnunet | |
745 gnunet-gtk | [] |
746 gnutls | [] [] |
747 gpe-aerial | [] [] [] [] [] [] [] |
748 gpe-beam | [] [] [] [] [] [] [] |
749 gpe-calendar | [] [] [] [] |
750 gpe-clock | [] [] [] [] [] [] [] [] |
751 gpe-conf | [] [] [] [] [] [] [] |
752 gpe-contacts | [] [] [] [] [] |
753 gpe-edit | [] [] [] [] [] [] [] [] [] |
754 gpe-filemanager | [] [] |
755 gpe-go | [] [] [] [] [] [] [] [] |
756 gpe-login | [] [] [] [] [] [] [] [] |
757 gpe-ownerinfo | [] [] [] [] [] [] [] [] |
758 gpe-package | [] [] |
759 gpe-sketchbook | [] [] [] [] [] [] [] [] |
760 gpe-su | [] [] [] [] [] [] [] [] |
761 gpe-taskmanager | [] [] [] [] [] [] [] [] |
762 gpe-timesheet | [] [] [] [] [] [] [] [] |
763 gpe-today | [] [] [] [] [] [] [] [] |
764 gpe-todo | [] [] [] [] |
765 gphoto2 | [] [] [] [] [] [] |
766 gprof | [] [] [] |
767 gpsdrive | [] [] |
768 gramadoir | [] [] |
769 grep | [] [] [] [] |
770 gretl | [] [] [] |
771 gsasl | [] [] [] |
772 gss | [] [] [] [] |
773 gst-plugins-bad | [] [] [] |
774 gst-plugins-base | [] [] |
775 gst-plugins-good | [] [] |
776 gst-plugins-ugly | [] [] [] |
777 gstreamer | [] [] [] [] |
778 gtick | [] |
779 gtkam | [] [] [] [] [] |
780 gtkorphan | [] |
781 gtkspell | [] [] [] [] [] [] [] [] |
782 gutenprint | [] |
783 hello | [] [] [] [] [] [] [] [] |
784 herrie | [] [] [] |
785 hylafax | |
786 idutils | [] [] [] [] [] |
787 indent | [] [] [] [] [] [] [] |
788 iso_15924 | |
789 iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] |
790 iso_3166_2 | |
791 iso_4217 | [] [] [] [] [] [] [] |
792 iso_639 | [] [] [] [] [] [] [] |
793 jpilot | |
794 jtag | [] |
795 jwhois | [] [] [] [] |
796 kbd | [] [] [] |
797 keytouch | [] |
798 keytouch-editor | [] |
799 keytouch-keyboa... | [] |
800 latrine | |
801 ld | [] |
802 leafpad | [] [] [] [] [] [] |
803 libc | [] [] [] [] |
804 libexif | [] [] |
805 libextractor | [] [] |
806 libgpewidget | [] [] [] [] [] [] [] [] |
807 libgpg-error | [] [] [] |
808 libgphoto2 | [] |
809 libgphoto2_port | [] [] [] |
810 libgsasl | [] [] [] [] |
811 libiconv | [] [] [] |
812 libidn | [] [] () |
813 lifelines | [] [] |
814 lilypond | |
815 lingoteach | [] |
816 lprng | [] |
817 lynx | [] [] [] |
818 m4 | [] [] [] [] [] |
819 mailfromd | [] |
820 mailutils | [] [] [] |
821 make | [] [] [] [] |
822 man-db | [] [] [] [] |
823 minicom | [] [] [] [] [] |
824 nano | [] [] [] [] |
825 opcodes | [] [] |
826 parted | [] |
827 pilot-qof | |
828 popt | [] [] [] [] |
829 psmisc | [] [] |
830 pwdutils | [] [] |
831 qof | [] [] |
832 radius | [] [] |
833 recode | [] [] [] [] [] [] [] |
834 rpm | [] [] [] [] |
835 screem | |
836 scrollkeeper | [] [] [] [] [] [] [] |
837 sed | [] [] [] [] [] [] [] [] [] |
838 shared-mime-info | [] [] [] [] [] [] |
839 sharutils | [] [] [] [] |
840 shishi | [] |
841 skencil | [] [] [] |
842 solfege | [] |
843 soundtracker | [] [] |
844 sp | |
845 system-tools-ba... | [] [] [] [] [] [] [] [] [] |
846 tar | [] [] [] [] |
847 texinfo | [] [] [] [] |
848 tin | () |
849 tuxpaint | [] [] [] [] [] [] |
850 unicode-han-tra... | |
851 unicode-transla... | |
852 util-linux | [] [] [] [] |
853 util-linux-ng | [] [] [] [] |
854 vorbis-tools | [] |
855 wastesedge | |
856 wdiff | [] [] [] [] [] [] [] |
857 wget | [] [] [] [] |
858 xchat | [] [] [] [] [] [] [] |
859 xkeyboard-config | [] [] [] |
860 xpad | [] [] [] |
861 +--------------------------------------------------+
862 or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta
863 0 5 77 31 53 4 58 72 3 45 46 9 45 122 3
864
865 tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu
866 +---------------------------------------------------+
867 Compendium | [] [] [] [] | 19
868 a2ps | [] [] [] | 19
869 aegis | [] | 1
870 ant-phone | [] [] | 6
871 anubis | [] [] [] | 11
872 ap-utils | () [] | 4
873 aspell | [] [] [] | 16
874 bash | [] | 6
875 bfd | | 2
876 bibshelf | [] | 7
877 binutils | [] [] [] [] | 9
878 bison | [] [] [] [] | 20
879 bison-runtime | [] [] [] [] | 18
880 bluez-pin | [] [] [] [] [] [] | 28
881 cflow | [] [] | 5
882 clisp | | 9
883 console-tools | [] [] | 5
884 coreutils | [] [] [] | 18
885 cpio | [] [] [] [] | 11
886 cpplib | [] [] [] [] [] | 12
887 cryptonit | [] | 6
888 dialog | [] [] [] | 9
889 diffutils | [] [] [] [] [] | 29
890 doodle | [] | 6
891 e2fsprogs | [] [] | 10
892 enscript | [] [] [] | 16
893 fetchmail | [] [] | 12
894 findutils | [] [] [] | 11
895 findutils_stable | [] [] [] [] | 18
896 flex | [] [] | 15
897 fslint | [] | 2
898 gas | [] | 3
899 gawk | [] [] [] | 16
900 gcal | [] | 5
901 gcc | [] [] [] | 7
902 gettext-examples | [] [] [] [] [] [] | 29
903 gettext-runtime | [] [] [] [] [] [] | 28
904 gettext-tools | [] [] [] [] [] | 20
905 gip | [] [] | 13
906 gliv | [] [] | 11
907 glunarclock | [] [] [] | 15
908 gmult | [] [] [] [] | 16
909 gnubiff | [] | 2
910 gnucash | () [] | 5
911 gnuedu | [] | 2
912 gnulib | [] | 10
913 gnunet | | 0
914 gnunet-gtk | [] [] | 3
915 gnutls | | 4
916 gpe-aerial | [] [] | 14
917 gpe-beam | [] [] | 14
918 gpe-calendar | [] [] | 7
919 gpe-clock | [] [] [] [] | 21
920 gpe-conf | [] [] [] | 16
921 gpe-contacts | [] [] | 10
922 gpe-edit | [] [] [] [] [] | 22
923 gpe-filemanager | [] [] | 7
924 gpe-go | [] [] [] [] | 19
925 gpe-login | [] [] [] [] [] | 21
926 gpe-ownerinfo | [] [] [] [] | 21
927 gpe-package | [] | 6
928 gpe-sketchbook | [] [] | 16
929 gpe-su | [] [] [] [] | 21
930 gpe-taskmanager | [] [] [] [] | 21
931 gpe-timesheet | [] [] [] [] | 18
932 gpe-today | [] [] [] [] [] | 21
933 gpe-todo | [] [] | 8
934 gphoto2 | [] [] [] [] | 21
935 gprof | [] [] | 13
936 gpsdrive | [] | 5
937 gramadoir | [] | 7
938 grep | [] | 12
939 gretl | | 6
940 gsasl | [] [] [] | 9
941 gss | [] | 7
942 gst-plugins-bad | [] [] [] | 13
943 gst-plugins-base | [] [] | 11
944 gst-plugins-good | [] [] [] [] [] | 16
945 gst-plugins-ugly | [] [] [] | 13
946 gstreamer | [] [] [] | 18
947 gtick | [] [] | 7
948 gtkam | [] | 16
949 gtkorphan | [] | 7
950 gtkspell | [] [] [] [] [] [] | 27
951 gutenprint | | 4
952 hello | [] [] [] [] [] | 38
953 herrie | [] [] | 8
954 hylafax | | 0
955 idutils | [] [] | 15
956 indent | [] [] [] [] [] | 28
957 iso_15924 | [] [] | 4
958 iso_3166 | [] [] [] [] [] [] [] [] [] | 54
959 iso_3166_2 | [] [] | 4
960 iso_4217 | [] [] [] [] [] | 24
961 iso_639 | [] [] [] [] [] | 26
962 jpilot | [] [] [] [] | 7
963 jtag | [] | 3
964 jwhois | [] [] [] | 13
965 kbd | [] [] [] | 13
966 keytouch | [] | 8
967 keytouch-editor | [] | 5
968 keytouch-keyboa... | [] | 5
969 latrine | [] [] | 5
970 ld | [] [] [] [] | 10
971 leafpad | [] [] [] [] [] | 24
972 libc | [] [] [] | 19
973 libexif | [] | 5
974 libextractor | [] | 5
975 libgpewidget | [] [] [] | 20
976 libgpg-error | [] | 6
977 libgphoto2 | [] [] | 9
978 libgphoto2_port | [] [] [] | 11
979 libgsasl | [] | 8
980 libiconv | [] [] | 11
981 libidn | [] [] | 11
982 lifelines | | 4
983 lilypond | [] | 6
984 lingoteach | [] | 6
985 lprng | [] | 2
986 lynx | [] [] [] | 15
987 m4 | [] [] [] | 18
988 mailfromd | [] [] | 3
989 mailutils | [] [] | 8
990 make | [] [] [] | 20
991 man-db | [] | 9
992 minicom | [] | 14
993 nano | [] [] [] | 20
994 opcodes | [] [] | 10
995 parted | [] [] [] | 11
996 pilot-qof | [] | 1
997 popt | [] [] [] [] | 18
998 psmisc | [] [] | 10
999 pwdutils | [] | 3
1000 qof | [] | 4
1001 radius | [] [] | 7
1002 recode | [] [] [] | 25
1003 rpm | [] [] [] [] | 13
1004 screem | [] | 2
1005 scrollkeeper | [] [] [] [] | 26
1006 sed | [] [] [] [] | 23
1007 shared-mime-info | [] [] [] | 29
1008 sharutils | [] [] [] | 23
1009 shishi | [] | 3
1010 skencil | [] | 7
1011 solfege | [] | 3
1012 soundtracker | [] [] | 9
1013 sp | [] | 3
1014 system-tools-ba... | [] [] [] [] [] [] [] | 38
1015 tar | [] [] [] | 17
1016 texinfo | [] [] [] | 15
1017 tin | | 1
1018 tuxpaint | [] [] [] | 19
1019 unicode-han-tra... | | 0
1020 unicode-transla... | | 2
1021 util-linux | [] [] [] | 20
1022 util-linux-ng | [] [] [] | 20
1023 vorbis-tools | [] [] | 4
1024 wastesedge | | 1
1025 wdiff | [] [] | 23
1026 wget | [] [] [] | 20
1027 xchat | [] [] [] [] | 29
1028 xkeyboard-config | [] [] [] | 14
1029 xpad | [] [] [] | 15
1030 +---------------------------------------------------+
1031 76 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu
1032 163 domains 0 3 1 74 51 0 143 21 1 57 7 45 0 2036
1033
1034 Some counters in the preceding matrix are higher than the number of
1035visible blocks let us expect. This is because a few extra PO files are
1036used for implementing regional variants of languages, or language
1037dialects.
1038
1039 For a PO file in the matrix above to be effective, the package to
1040which it applies should also have been internationalized and
1041distributed as such by its maintainer. There might be an observable
1042lag between the mere existence a PO file and its wide availability in a
1043distribution.
1044
1045 If November 2007 seems to be old, you may fetch a more recent copy
1046of this `ABOUT-NLS' file on most GNU archive sites. The most
1047up-to-date matrix with full percentage details can be found at
1048`http://translationproject.org/extra/matrix.html'.
1049
10501.6 Using `gettext' in new packages
1051===================================
1052
1053If you are writing a freely available program and want to
1054internationalize it you are welcome to use GNU `gettext' in your
1055package. Of course you have to respect the GNU Library General Public
1056License which covers the use of the GNU `gettext' library. This means
1057in particular that even non-free programs can use `libintl' as a shared
1058library, whereas only free software can use `libintl' as a static
1059library or use modified versions of `libintl'.
1060
1061 Once the sources are changed appropriately and the setup can handle
1062the use of `gettext' the only thing missing are the translations. The
1063Free Translation Project is also available for packages which are not
1064developed inside the GNU project. Therefore the information given above
1065applies also for every other Free Software Project. Contact
1066`coordinator@translationproject.org' to make the `.pot' files available
1067to the translation teams.
1068
diff --git a/pathologist/AUTHORS b/pathologist/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pathologist/AUTHORS
diff --git a/pathologist/COPYING b/pathologist/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/pathologist/COPYING
@@ -0,0 +1,674 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The GNU General Public License is a free, copyleft license for
11software and other kinds of works.
12
13 The licenses for most software and other practical works are designed
14to take away your freedom to share and change the works. By contrast,
15the GNU General Public License is intended to guarantee your freedom to
16share and change all versions of a program--to make sure it remains free
17software for all its users. We, the Free Software Foundation, use the
18GNU General Public License for most of our software; it applies also to
19any other work released this way by its authors. You can apply it to
20your programs, too.
21
22 When we speak of free software, we are referring to freedom, not
23price. Our General Public Licenses are designed to make sure that you
24have the freedom to distribute copies of free software (and charge for
25them if you wish), that you receive source code or can get it if you
26want it, that you can change the software or use pieces of it in new
27free programs, and that you know you can do these things.
28
29 To protect your rights, we need to prevent others from denying you
30these rights or asking you to surrender the rights. Therefore, you have
31certain responsibilities if you distribute copies of the software, or if
32you modify it: responsibilities to respect the freedom of others.
33
34 For example, if you distribute copies of such a program, whether
35gratis or for a fee, you must pass on to the recipients the same
36freedoms that you received. You must make sure that they, too, receive
37or can get the source code. And you must show them these terms so they
38know their rights.
39
40 Developers that use the GNU GPL protect your rights with two steps:
41(1) assert copyright on the software, and (2) offer you this License
42giving you legal permission to copy, distribute and/or modify it.
43
44 For the developers' and authors' protection, the GPL clearly explains
45that there is no warranty for this free software. For both users' and
46authors' sake, the GPL requires that modified versions be marked as
47changed, so that their problems will not be attributed erroneously to
48authors of previous versions.
49
50 Some devices are designed to deny users access to install or run
51modified versions of the software inside them, although the manufacturer
52can do so. This is fundamentally incompatible with the aim of
53protecting users' freedom to change the software. The systematic
54pattern of such abuse occurs in the area of products for individuals to
55use, which is precisely where it is most unacceptable. Therefore, we
56have designed this version of the GPL to prohibit the practice for those
57products. If such problems arise substantially in other domains, we
58stand ready to extend this provision to those domains in future versions
59of the GPL, as needed to protect the freedom of users.
60
61 Finally, every program is threatened constantly by software patents.
62States should not allow patents to restrict development and use of
63software on general-purpose computers, but in those that do, we wish to
64avoid the special danger that patents applied to a free program could
65make it effectively proprietary. To prevent this, the GPL assures that
66patents cannot be used to render the program non-free.
67
68 The precise terms and conditions for copying, distribution and
69modification follow.
70
71 TERMS AND CONDITIONS
72
73 0. Definitions.
74
75 "This License" refers to version 3 of the GNU General Public License.
76
77 "Copyright" also means copyright-like laws that apply to other kinds of
78works, such as semiconductor masks.
79
80 "The Program" refers to any copyrightable work licensed under this
81License. Each licensee is addressed as "you". "Licensees" and
82"recipients" may be individuals or organizations.
83
84 To "modify" a work means to copy from or adapt all or part of the work
85in a fashion requiring copyright permission, other than the making of an
86exact copy. The resulting work is called a "modified version" of the
87earlier work or a work "based on" the earlier work.
88
89 A "covered work" means either the unmodified Program or a work based
90on the Program.
91
92 To "propagate" a work means to do anything with it that, without
93permission, would make you directly or secondarily liable for
94infringement under applicable copyright law, except executing it on a
95computer or modifying a private copy. Propagation includes copying,
96distribution (with or without modification), making available to the
97public, and in some countries other activities as well.
98
99 To "convey" a work means any kind of propagation that enables other
100parties to make or receive copies. Mere interaction with a user through
101a computer network, with no transfer of a copy, is not conveying.
102
103 An interactive user interface displays "Appropriate Legal Notices"
104to the extent that it includes a convenient and prominently visible
105feature that (1) displays an appropriate copyright notice, and (2)
106tells the user that there is no warranty for the work (except to the
107extent that warranties are provided), that licensees may convey the
108work under this License, and how to view a copy of this License. If
109the interface presents a list of user commands or options, such as a
110menu, a prominent item in the list meets this criterion.
111
112 1. Source Code.
113
114 The "source code" for a work means the preferred form of the work
115for making modifications to it. "Object code" means any non-source
116form of a work.
117
118 A "Standard Interface" means an interface that either is an official
119standard defined by a recognized standards body, or, in the case of
120interfaces specified for a particular programming language, one that
121is widely used among developers working in that language.
122
123 The "System Libraries" of an executable work include anything, other
124than the work as a whole, that (a) is included in the normal form of
125packaging a Major Component, but which is not part of that Major
126Component, and (b) serves only to enable use of the work with that
127Major Component, or to implement a Standard Interface for which an
128implementation is available to the public in source code form. A
129"Major Component", in this context, means a major essential component
130(kernel, window system, and so on) of the specific operating system
131(if any) on which the executable work runs, or a compiler used to
132produce the work, or an object code interpreter used to run it.
133
134 The "Corresponding Source" for a work in object code form means all
135the source code needed to generate, install, and (for an executable
136work) run the object code and to modify the work, including scripts to
137control those activities. However, it does not include the work's
138System Libraries, or general-purpose tools or generally available free
139programs which are used unmodified in performing those activities but
140which are not part of the work. For example, Corresponding Source
141includes interface definition files associated with source files for
142the work, and the source code for shared libraries and dynamically
143linked subprograms that the work is specifically designed to require,
144such as by intimate data communication or control flow between those
145subprograms and other parts of the work.
146
147 The Corresponding Source need not include anything that users
148can regenerate automatically from other parts of the Corresponding
149Source.
150
151 The Corresponding Source for a work in source code form is that
152same work.
153
154 2. Basic Permissions.
155
156 All rights granted under this License are granted for the term of
157copyright on the Program, and are irrevocable provided the stated
158conditions are met. This License explicitly affirms your unlimited
159permission to run the unmodified Program. The output from running a
160covered work is covered by this License only if the output, given its
161content, constitutes a covered work. This License acknowledges your
162rights of fair use or other equivalent, as provided by copyright law.
163
164 You may make, run and propagate covered works that you do not
165convey, without conditions so long as your license otherwise remains
166in force. You may convey covered works to others for the sole purpose
167of having them make modifications exclusively for you, or provide you
168with facilities for running those works, provided that you comply with
169the terms of this License in conveying all material for which you do
170not control copyright. Those thus making or running the covered works
171for you must do so exclusively on your behalf, under your direction
172and control, on terms that prohibit them from making any copies of
173your copyrighted material outside their relationship with you.
174
175 Conveying under any other circumstances is permitted solely under
176the conditions stated below. Sublicensing is not allowed; section 10
177makes it unnecessary.
178
179 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
181 No covered work shall be deemed part of an effective technological
182measure under any applicable law fulfilling obligations under article
18311 of the WIPO copyright treaty adopted on 20 December 1996, or
184similar laws prohibiting or restricting circumvention of such
185measures.
186
187 When you convey a covered work, you waive any legal power to forbid
188circumvention of technological measures to the extent such circumvention
189is effected by exercising rights under this License with respect to
190the covered work, and you disclaim any intention to limit operation or
191modification of the work as a means of enforcing, against the work's
192users, your or third parties' legal rights to forbid circumvention of
193technological measures.
194
195 4. Conveying Verbatim Copies.
196
197 You may convey verbatim copies of the Program's source code as you
198receive it, in any medium, provided that you conspicuously and
199appropriately publish on each copy an appropriate copyright notice;
200keep intact all notices stating that this License and any
201non-permissive terms added in accord with section 7 apply to the code;
202keep intact all notices of the absence of any warranty; and give all
203recipients a copy of this License along with the Program.
204
205 You may charge any price or no price for each copy that you convey,
206and you may offer support or warranty protection for a fee.
207
208 5. Conveying Modified Source Versions.
209
210 You may convey a work based on the Program, or the modifications to
211produce it from the Program, in the form of source code under the
212terms of section 4, provided that you also meet all of these conditions:
213
214 a) The work must carry prominent notices stating that you modified
215 it, and giving a relevant date.
216
217 b) The work must carry prominent notices stating that it is
218 released under this License and any conditions added under section
219 7. This requirement modifies the requirement in section 4 to
220 "keep intact all notices".
221
222 c) You must license the entire work, as a whole, under this
223 License to anyone who comes into possession of a copy. This
224 License will therefore apply, along with any applicable section 7
225 additional terms, to the whole of the work, and all its parts,
226 regardless of how they are packaged. This License gives no
227 permission to license the work in any other way, but it does not
228 invalidate such permission if you have separately received it.
229
230 d) If the work has interactive user interfaces, each must display
231 Appropriate Legal Notices; however, if the Program has interactive
232 interfaces that do not display Appropriate Legal Notices, your
233 work need not make them do so.
234
235 A compilation of a covered work with other separate and independent
236works, which are not by their nature extensions of the covered work,
237and which are not combined with it such as to form a larger program,
238in or on a volume of a storage or distribution medium, is called an
239"aggregate" if the compilation and its resulting copyright are not
240used to limit the access or legal rights of the compilation's users
241beyond what the individual works permit. Inclusion of a covered work
242in an aggregate does not cause this License to apply to the other
243parts of the aggregate.
244
245 6. Conveying Non-Source Forms.
246
247 You may convey a covered work in object code form under the terms
248of sections 4 and 5, provided that you also convey the
249machine-readable Corresponding Source under the terms of this License,
250in one of these ways:
251
252 a) Convey the object code in, or embodied in, a physical product
253 (including a physical distribution medium), accompanied by the
254 Corresponding Source fixed on a durable physical medium
255 customarily used for software interchange.
256
257 b) Convey the object code in, or embodied in, a physical product
258 (including a physical distribution medium), accompanied by a
259 written offer, valid for at least three years and valid for as
260 long as you offer spare parts or customer support for that product
261 model, to give anyone who possesses the object code either (1) a
262 copy of the Corresponding Source for all the software in the
263 product that is covered by this License, on a durable physical
264 medium customarily used for software interchange, for a price no
265 more than your reasonable cost of physically performing this
266 conveying of source, or (2) access to copy the
267 Corresponding Source from a network server at no charge.
268
269 c) Convey individual copies of the object code with a copy of the
270 written offer to provide the Corresponding Source. This
271 alternative is allowed only occasionally and noncommercially, and
272 only if you received the object code with such an offer, in accord
273 with subsection 6b.
274
275 d) Convey the object code by offering access from a designated
276 place (gratis or for a charge), and offer equivalent access to the
277 Corresponding Source in the same way through the same place at no
278 further charge. You need not require recipients to copy the
279 Corresponding Source along with the object code. If the place to
280 copy the object code is a network server, the Corresponding Source
281 may be on a different server (operated by you or a third party)
282 that supports equivalent copying facilities, provided you maintain
283 clear directions next to the object code saying where to find the
284 Corresponding Source. Regardless of what server hosts the
285 Corresponding Source, you remain obligated to ensure that it is
286 available for as long as needed to satisfy these requirements.
287
288 e) Convey the object code using peer-to-peer transmission, provided
289 you inform other peers where the object code and Corresponding
290 Source of the work are being offered to the general public at no
291 charge under subsection 6d.
292
293 A separable portion of the object code, whose source code is excluded
294from the Corresponding Source as a System Library, need not be
295included in conveying the object code work.
296
297 A "User Product" is either (1) a "consumer product", which means any
298tangible personal property which is normally used for personal, family,
299or household purposes, or (2) anything designed or sold for incorporation
300into a dwelling. In determining whether a product is a consumer product,
301doubtful cases shall be resolved in favor of coverage. For a particular
302product received by a particular user, "normally used" refers to a
303typical or common use of that class of product, regardless of the status
304of the particular user or of the way in which the particular user
305actually uses, or expects or is expected to use, the product. A product
306is a consumer product regardless of whether the product has substantial
307commercial, industrial or non-consumer uses, unless such uses represent
308the only significant mode of use of the product.
309
310 "Installation Information" for a User Product means any methods,
311procedures, authorization keys, or other information required to install
312and execute modified versions of a covered work in that User Product from
313a modified version of its Corresponding Source. The information must
314suffice to ensure that the continued functioning of the modified object
315code is in no case prevented or interfered with solely because
316modification has been made.
317
318 If you convey an object code work under this section in, or with, or
319specifically for use in, a User Product, and the conveying occurs as
320part of a transaction in which the right of possession and use of the
321User Product is transferred to the recipient in perpetuity or for a
322fixed term (regardless of how the transaction is characterized), the
323Corresponding Source conveyed under this section must be accompanied
324by the Installation Information. But this requirement does not apply
325if neither you nor any third party retains the ability to install
326modified object code on the User Product (for example, the work has
327been installed in ROM).
328
329 The requirement to provide Installation Information does not include a
330requirement to continue to provide support service, warranty, or updates
331for a work that has been modified or installed by the recipient, or for
332the User Product in which it has been modified or installed. Access to a
333network may be denied when the modification itself materially and
334adversely affects the operation of the network or violates the rules and
335protocols for communication across the network.
336
337 Corresponding Source conveyed, and Installation Information provided,
338in accord with this section must be in a format that is publicly
339documented (and with an implementation available to the public in
340source code form), and must require no special password or key for
341unpacking, reading or copying.
342
343 7. Additional Terms.
344
345 "Additional permissions" are terms that supplement the terms of this
346License by making exceptions from one or more of its conditions.
347Additional permissions that are applicable to the entire Program shall
348be treated as though they were included in this License, to the extent
349that they are valid under applicable law. If additional permissions
350apply only to part of the Program, that part may be used separately
351under those permissions, but the entire Program remains governed by
352this License without regard to the additional permissions.
353
354 When you convey a copy of a covered work, you may at your option
355remove any additional permissions from that copy, or from any part of
356it. (Additional permissions may be written to require their own
357removal in certain cases when you modify the work.) You may place
358additional permissions on material, added by you to a covered work,
359for which you have or can give appropriate copyright permission.
360
361 Notwithstanding any other provision of this License, for material you
362add to a covered work, you may (if authorized by the copyright holders of
363that material) supplement the terms of this License with terms:
364
365 a) Disclaiming warranty or limiting liability differently from the
366 terms of sections 15 and 16 of this License; or
367
368 b) Requiring preservation of specified reasonable legal notices or
369 author attributions in that material or in the Appropriate Legal
370 Notices displayed by works containing it; or
371
372 c) Prohibiting misrepresentation of the origin of that material, or
373 requiring that modified versions of such material be marked in
374 reasonable ways as different from the original version; or
375
376 d) Limiting the use for publicity purposes of names of licensors or
377 authors of the material; or
378
379 e) Declining to grant rights under trademark law for use of some
380 trade names, trademarks, or service marks; or
381
382 f) Requiring indemnification of licensors and authors of that
383 material by anyone who conveys the material (or modified versions of
384 it) with contractual assumptions of liability to the recipient, for
385 any liability that these contractual assumptions directly impose on
386 those licensors and authors.
387
388 All other non-permissive additional terms are considered "further
389restrictions" within the meaning of section 10. If the Program as you
390received it, or any part of it, contains a notice stating that it is
391governed by this License along with a term that is a further
392restriction, you may remove that term. If a license document contains
393a further restriction but permits relicensing or conveying under this
394License, you may add to a covered work material governed by the terms
395of that license document, provided that the further restriction does
396not survive such relicensing or conveying.
397
398 If you add terms to a covered work in accord with this section, you
399must place, in the relevant source files, a statement of the
400additional terms that apply to those files, or a notice indicating
401where to find the applicable terms.
402
403 Additional terms, permissive or non-permissive, may be stated in the
404form of a separately written license, or stated as exceptions;
405the above requirements apply either way.
406
407 8. Termination.
408
409 You may not propagate or modify a covered work except as expressly
410provided under this License. Any attempt otherwise to propagate or
411modify it is void, and will automatically terminate your rights under
412this License (including any patent licenses granted under the third
413paragraph of section 11).
414
415 However, if you cease all violation of this License, then your
416license from a particular copyright holder is reinstated (a)
417provisionally, unless and until the copyright holder explicitly and
418finally terminates your license, and (b) permanently, if the copyright
419holder fails to notify you of the violation by some reasonable means
420prior to 60 days after the cessation.
421
422 Moreover, your license from a particular copyright holder is
423reinstated permanently if the copyright holder notifies you of the
424violation by some reasonable means, this is the first time you have
425received notice of violation of this License (for any work) from that
426copyright holder, and you cure the violation prior to 30 days after
427your receipt of the notice.
428
429 Termination of your rights under this section does not terminate the
430licenses of parties who have received copies or rights from you under
431this License. If your rights have been terminated and not permanently
432reinstated, you do not qualify to receive new licenses for the same
433material under section 10.
434
435 9. Acceptance Not Required for Having Copies.
436
437 You are not required to accept this License in order to receive or
438run a copy of the Program. Ancillary propagation of a covered work
439occurring solely as a consequence of using peer-to-peer transmission
440to receive a copy likewise does not require acceptance. However,
441nothing other than this License grants you permission to propagate or
442modify any covered work. These actions infringe copyright if you do
443not accept this License. Therefore, by modifying or propagating a
444covered work, you indicate your acceptance of this License to do so.
445
446 10. Automatic Licensing of Downstream Recipients.
447
448 Each time you convey a covered work, the recipient automatically
449receives a license from the original licensors, to run, modify and
450propagate that work, subject to this License. You are not responsible
451for enforcing compliance by third parties with this License.
452
453 An "entity transaction" is a transaction transferring control of an
454organization, or substantially all assets of one, or subdividing an
455organization, or merging organizations. If propagation of a covered
456work results from an entity transaction, each party to that
457transaction who receives a copy of the work also receives whatever
458licenses to the work the party's predecessor in interest had or could
459give under the previous paragraph, plus a right to possession of the
460Corresponding Source of the work from the predecessor in interest, if
461the predecessor has it or can get it with reasonable efforts.
462
463 You may not impose any further restrictions on the exercise of the
464rights granted or affirmed under this License. For example, you may
465not impose a license fee, royalty, or other charge for exercise of
466rights granted under this License, and you may not initiate litigation
467(including a cross-claim or counterclaim in a lawsuit) alleging that
468any patent claim is infringed by making, using, selling, offering for
469sale, or importing the Program or any portion of it.
470
471 11. Patents.
472
473 A "contributor" is a copyright holder who authorizes use under this
474License of the Program or a work on which the Program is based. The
475work thus licensed is called the contributor's "contributor version".
476
477 A contributor's "essential patent claims" are all patent claims
478owned or controlled by the contributor, whether already acquired or
479hereafter acquired, that would be infringed by some manner, permitted
480by this License, of making, using, or selling its contributor version,
481but do not include claims that would be infringed only as a
482consequence of further modification of the contributor version. For
483purposes of this definition, "control" includes the right to grant
484patent sublicenses in a manner consistent with the requirements of
485this License.
486
487 Each contributor grants you a non-exclusive, worldwide, royalty-free
488patent license under the contributor's essential patent claims, to
489make, use, sell, offer for sale, import and otherwise run, modify and
490propagate the contents of its contributor version.
491
492 In the following three paragraphs, a "patent license" is any express
493agreement or commitment, however denominated, not to enforce a patent
494(such as an express permission to practice a patent or covenant not to
495sue for patent infringement). To "grant" such a patent license to a
496party means to make such an agreement or commitment not to enforce a
497patent against the party.
498
499 If you convey a covered work, knowingly relying on a patent license,
500and the Corresponding Source of the work is not available for anyone
501to copy, free of charge and under the terms of this License, through a
502publicly available network server or other readily accessible means,
503then you must either (1) cause the Corresponding Source to be so
504available, or (2) arrange to deprive yourself of the benefit of the
505patent license for this particular work, or (3) arrange, in a manner
506consistent with the requirements of this License, to extend the patent
507license to downstream recipients. "Knowingly relying" means you have
508actual knowledge that, but for the patent license, your conveying the
509covered work in a country, or your recipient's use of the covered work
510in a country, would infringe one or more identifiable patents in that
511country that you have reason to believe are valid.
512
513 If, pursuant to or in connection with a single transaction or
514arrangement, you convey, or propagate by procuring conveyance of, a
515covered work, and grant a patent license to some of the parties
516receiving the covered work authorizing them to use, propagate, modify
517or convey a specific copy of the covered work, then the patent license
518you grant is automatically extended to all recipients of the covered
519work and works based on it.
520
521 A patent license is "discriminatory" if it does not include within
522the scope of its coverage, prohibits the exercise of, or is
523conditioned on the non-exercise of one or more of the rights that are
524specifically granted under this License. You may not convey a covered
525work if you are a party to an arrangement with a third party that is
526in the business of distributing software, under which you make payment
527to the third party based on the extent of your activity of conveying
528the work, and under which the third party grants, to any of the
529parties who would receive the covered work from you, a discriminatory
530patent license (a) in connection with copies of the covered work
531conveyed by you (or copies made from those copies), or (b) primarily
532for and in connection with specific products or compilations that
533contain the covered work, unless you entered into that arrangement,
534or that patent license was granted, prior to 28 March 2007.
535
536 Nothing in this License shall be construed as excluding or limiting
537any implied license or other defenses to infringement that may
538otherwise be available to you under applicable patent law.
539
540 12. No Surrender of Others' Freedom.
541
542 If conditions are imposed on you (whether by court order, agreement or
543otherwise) that contradict the conditions of this License, they do not
544excuse you from the conditions of this License. If you cannot convey a
545covered work so as to satisfy simultaneously your obligations under this
546License and any other pertinent obligations, then as a consequence you may
547not convey it at all. For example, if you agree to terms that obligate you
548to collect a royalty for further conveying from those to whom you convey
549the Program, the only way you could satisfy both those terms and this
550License would be to refrain entirely from conveying the Program.
551
552 13. Use with the GNU Affero General Public License.
553
554 Notwithstanding any other provision of this License, you have
555permission to link or combine any covered work with a work licensed
556under version 3 of the GNU Affero General Public License into a single
557combined work, and to convey the resulting work. The terms of this
558License will continue to apply to the part which is the covered work,
559but the special requirements of the GNU Affero General Public License,
560section 13, concerning interaction through a network will apply to the
561combination as such.
562
563 14. Revised Versions of this License.
564
565 The Free Software Foundation may publish revised and/or new versions of
566the GNU General Public License from time to time. Such new versions will
567be similar in spirit to the present version, but may differ in detail to
568address new problems or concerns.
569
570 Each version is given a distinguishing version number. If the
571Program specifies that a certain numbered version of the GNU General
572Public License "or any later version" applies to it, you have the
573option of following the terms and conditions either of that numbered
574version or of any later version published by the Free Software
575Foundation. If the Program does not specify a version number of the
576GNU General Public License, you may choose any version ever published
577by the Free Software Foundation.
578
579 If the Program specifies that a proxy can decide which future
580versions of the GNU General Public License can be used, that proxy's
581public statement of acceptance of a version permanently authorizes you
582to choose that version for the Program.
583
584 Later license versions may give you additional or different
585permissions. However, no additional obligations are imposed on any
586author or copyright holder as a result of your choosing to follow a
587later version.
588
589 15. Disclaimer of Warranty.
590
591 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
600 16. Limitation of Liability.
601
602 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610SUCH DAMAGES.
611
612 17. Interpretation of Sections 15 and 16.
613
614 If the disclaimer of warranty and limitation of liability provided
615above cannot be given local legal effect according to their terms,
616reviewing courts shall apply local law that most closely approximates
617an absolute waiver of all civil liability in connection with the
618Program, unless a warranty or assumption of liability accompanies a
619copy of the Program in return for a fee.
620
621 END OF TERMS AND CONDITIONS
622
623 How to Apply These Terms to Your New Programs
624
625 If you develop a new program, and you want it to be of the greatest
626possible use to the public, the best way to achieve this is to make it
627free software which everyone can redistribute and change under these terms.
628
629 To do so, attach the following notices to the program. It is safest
630to attach them to the start of each source file to most effectively
631state the exclusion of warranty; and each file should have at least
632the "copyright" line and a pointer to where the full notice is found.
633
634 <one line to give the program's name and a brief idea of what it does.>
635 Copyright (C) <year> <name of author>
636
637 This program is free software: you can redistribute it and/or modify
638 it under the terms of the GNU General Public License as published by
639 the Free Software Foundation, either version 3 of the License, or
640 (at your option) any later version.
641
642 This program is distributed in the hope that it will be useful,
643 but WITHOUT ANY WARRANTY; without even the implied warranty of
644 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 GNU General Public License for more details.
646
647 You should have received a copy of the GNU General Public License
648 along with this program. If not, see <http://www.gnu.org/licenses/>.
649
650Also add information on how to contact you by electronic and paper mail.
651
652 If the program does terminal interaction, make it output a short
653notice like this when it starts in an interactive mode:
654
655 <program> Copyright (C) <year> <name of author>
656 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 This is free software, and you are welcome to redistribute it
658 under certain conditions; type `show c' for details.
659
660The hypothetical commands `show w' and `show c' should show the appropriate
661parts of the General Public License. Of course, your program's commands
662might be different; for a GUI interface, you would use an "about box".
663
664 You should also get your employer (if you work as a programmer) or school,
665if any, to sign a "copyright disclaimer" for the program, if necessary.
666For more information on this, and how to apply and follow the GNU GPL, see
667<http://www.gnu.org/licenses/>.
668
669 The GNU General Public License does not permit incorporating your program
670into proprietary programs. If your program is a subroutine library, you
671may consider it more useful to permit linking proprietary applications with
672the library. If this is what you want to do, use the GNU Lesser General
673Public License instead of this License. But first, please read
674<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/pathologist/ChangeLog b/pathologist/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pathologist/ChangeLog
diff --git a/pathologist/INSTALL b/pathologist/INSTALL
new file mode 100644
index 0000000..7d1c323
--- /dev/null
+++ b/pathologist/INSTALL
@@ -0,0 +1,365 @@
1Installation Instructions
2*************************
3
4Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
52006, 2007, 2008, 2009 Free Software Foundation, Inc.
6
7 Copying and distribution of this file, with or without modification,
8are permitted in any medium without royalty provided the copyright
9notice and this notice are preserved. This file is offered as-is,
10without warranty of any kind.
11
12Basic Installation
13==================
14
15 Briefly, the shell commands `./configure; make; make install' should
16configure, build, and install this package. The following
17more-detailed instructions are generic; see the `README' file for
18instructions specific to this package. Some packages provide this
19`INSTALL' file but do not implement all of the features documented
20below. The lack of an optional feature in a given package is not
21necessarily a bug. More recommendations for GNU packages can be found
22in *note Makefile Conventions: (standards)Makefile Conventions.
23
24 The `configure' shell script attempts to guess correct values for
25various system-dependent variables used during compilation. It uses
26those values to create a `Makefile' in each directory of the package.
27It may also create one or more `.h' files containing system-dependent
28definitions. Finally, it creates a shell script `config.status' that
29you can run in the future to recreate the current configuration, and a
30file `config.log' containing compiler output (useful mainly for
31debugging `configure').
32
33 It can also use an optional file (typically called `config.cache'
34and enabled with `--cache-file=config.cache' or simply `-C') that saves
35the results of its tests to speed up reconfiguring. Caching is
36disabled by default to prevent problems with accidental use of stale
37cache files.
38
39 If you need to do unusual things to compile the package, please try
40to figure out how `configure' could check whether to do them, and mail
41diffs or instructions to the address given in the `README' so they can
42be considered for the next release. If you are using the cache, and at
43some point `config.cache' contains results you don't want to keep, you
44may remove or edit it.
45
46 The file `configure.ac' (or `configure.in') is used to create
47`configure' by a program called `autoconf'. You need `configure.ac' if
48you want to change it or regenerate `configure' using a newer version
49of `autoconf'.
50
51 The simplest way to compile this package is:
52
53 1. `cd' to the directory containing the package's source code and type
54 `./configure' to configure the package for your system.
55
56 Running `configure' might take a while. While running, it prints
57 some messages telling which features it is checking for.
58
59 2. Type `make' to compile the package.
60
61 3. Optionally, type `make check' to run any self-tests that come with
62 the package, generally using the just-built uninstalled binaries.
63
64 4. Type `make install' to install the programs and any data files and
65 documentation. When installing into a prefix owned by root, it is
66 recommended that the package be configured and built as a regular
67 user, and only the `make install' phase executed with root
68 privileges.
69
70 5. Optionally, type `make installcheck' to repeat any self-tests, but
71 this time using the binaries in their final installed location.
72 This target does not install anything. Running this target as a
73 regular user, particularly if the prior `make install' required
74 root privileges, verifies that the installation completed
75 correctly.
76
77 6. You can remove the program binaries and object files from the
78 source code directory by typing `make clean'. To also remove the
79 files that `configure' created (so you can compile the package for
80 a different kind of computer), type `make distclean'. There is
81 also a `make maintainer-clean' target, but that is intended mainly
82 for the package's developers. If you use it, you may have to get
83 all sorts of other programs in order to regenerate files that came
84 with the distribution.
85
86 7. Often, you can also type `make uninstall' to remove the installed
87 files again. In practice, not all packages have tested that
88 uninstallation works correctly, even though it is required by the
89 GNU Coding Standards.
90
91 8. Some packages, particularly those that use Automake, provide `make
92 distcheck', which can by used by developers to test that all other
93 targets like `make install' and `make uninstall' work correctly.
94 This target is generally not run by end users.
95
96Compilers and Options
97=====================
98
99 Some systems require unusual options for compilation or linking that
100the `configure' script does not know about. Run `./configure --help'
101for details on some of the pertinent environment variables.
102
103 You can give `configure' initial values for configuration parameters
104by setting variables in the command line or in the environment. Here
105is an example:
106
107 ./configure CC=c99 CFLAGS=-g LIBS=-lposix
108
109 *Note Defining Variables::, for more details.
110
111Compiling For Multiple Architectures
112====================================
113
114 You can compile the package for more than one kind of computer at the
115same time, by placing the object files for each architecture in their
116own directory. To do this, you can use GNU `make'. `cd' to the
117directory where you want the object files and executables to go and run
118the `configure' script. `configure' automatically checks for the
119source code in the directory that `configure' is in and in `..'. This
120is known as a "VPATH" build.
121
122 With a non-GNU `make', it is safer to compile the package for one
123architecture at a time in the source code directory. After you have
124installed the package for one architecture, use `make distclean' before
125reconfiguring for another architecture.
126
127 On MacOS X 10.5 and later systems, you can create libraries and
128executables that work on multiple system types--known as "fat" or
129"universal" binaries--by specifying multiple `-arch' options to the
130compiler but only a single `-arch' option to the preprocessor. Like
131this:
132
133 ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
134 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
135 CPP="gcc -E" CXXCPP="g++ -E"
136
137 This is not guaranteed to produce working output in all cases, you
138may have to build one architecture at a time and combine the results
139using the `lipo' tool if you have problems.
140
141Installation Names
142==================
143
144 By default, `make install' installs the package's commands under
145`/usr/local/bin', include files under `/usr/local/include', etc. You
146can specify an installation prefix other than `/usr/local' by giving
147`configure' the option `--prefix=PREFIX', where PREFIX must be an
148absolute file name.
149
150 You can specify separate installation prefixes for
151architecture-specific files and architecture-independent files. If you
152pass the option `--exec-prefix=PREFIX' to `configure', the package uses
153PREFIX as the prefix for installing programs and libraries.
154Documentation and other data files still use the regular prefix.
155
156 In addition, if you use an unusual directory layout you can give
157options like `--bindir=DIR' to specify different values for particular
158kinds of files. Run `configure --help' for a list of the directories
159you can set and what kinds of files go in them. In general, the
160default for these options is expressed in terms of `${prefix}', so that
161specifying just `--prefix' will affect all of the other directory
162specifications that were not explicitly provided.
163
164 The most portable way to affect installation locations is to pass the
165correct locations to `configure'; however, many packages provide one or
166both of the following shortcuts of passing variable assignments to the
167`make install' command line to change installation locations without
168having to reconfigure or recompile.
169
170 The first method involves providing an override variable for each
171affected directory. For example, `make install
172prefix=/alternate/directory' will choose an alternate location for all
173directory configuration variables that were expressed in terms of
174`${prefix}'. Any directories that were specified during `configure',
175but not in terms of `${prefix}', must each be overridden at install
176time for the entire installation to be relocated. The approach of
177makefile variable overrides for each directory variable is required by
178the GNU Coding Standards, and ideally causes no recompilation.
179However, some platforms have known limitations with the semantics of
180shared libraries that end up requiring recompilation when using this
181method, particularly noticeable in packages that use GNU Libtool.
182
183 The second method involves providing the `DESTDIR' variable. For
184example, `make install DESTDIR=/alternate/directory' will prepend
185`/alternate/directory' before all installation names. The approach of
186`DESTDIR' overrides is not required by the GNU Coding Standards, and
187does not work on platforms that have drive letters. On the other hand,
188it does better at avoiding recompilation issues, and works well even
189when some directory options were not specified in terms of `${prefix}'
190at `configure' time.
191
192Optional Features
193=================
194
195 If the package supports it, you can cause programs to be installed
196with an extra prefix or suffix on their names by giving `configure' the
197option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
198
199 Some packages pay attention to `--enable-FEATURE' options to
200`configure', where FEATURE indicates an optional part of the package.
201They may also pay attention to `--with-PACKAGE' options, where PACKAGE
202is something like `gnu-as' or `x' (for the X Window System). The
203`README' should mention any `--enable-' and `--with-' options that the
204package recognizes.
205
206 For packages that use the X Window System, `configure' can usually
207find the X include and library files automatically, but if it doesn't,
208you can use the `configure' options `--x-includes=DIR' and
209`--x-libraries=DIR' to specify their locations.
210
211 Some packages offer the ability to configure how verbose the
212execution of `make' will be. For these packages, running `./configure
213--enable-silent-rules' sets the default to minimal output, which can be
214overridden with `make V=1'; while running `./configure
215--disable-silent-rules' sets the default to verbose, which can be
216overridden with `make V=0'.
217
218Particular systems
219==================
220
221 On HP-UX, the default C compiler is not ANSI C compatible. If GNU
222CC is not installed, it is recommended to use the following options in
223order to use an ANSI C compiler:
224
225 ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
226
227and if that doesn't work, install pre-built binaries of GCC for HP-UX.
228
229 On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
230parse its `<wchar.h>' header file. The option `-nodtk' can be used as
231a workaround. If GNU CC is not installed, it is therefore recommended
232to try
233
234 ./configure CC="cc"
235
236and if that doesn't work, try
237
238 ./configure CC="cc -nodtk"
239
240 On Solaris, don't put `/usr/ucb' early in your `PATH'. This
241directory contains several dysfunctional programs; working variants of
242these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
243in your `PATH', put it _after_ `/usr/bin'.
244
245 On Haiku, software installed for all users goes in `/boot/common',
246not `/usr/local'. It is recommended to use the following options:
247
248 ./configure --prefix=/boot/common
249
250Specifying the System Type
251==========================
252
253 There may be some features `configure' cannot figure out
254automatically, but needs to determine by the type of machine the package
255will run on. Usually, assuming the package is built to be run on the
256_same_ architectures, `configure' can figure that out, but if it prints
257a message saying it cannot guess the machine type, give it the
258`--build=TYPE' option. TYPE can either be a short name for the system
259type, such as `sun4', or a canonical name which has the form:
260
261 CPU-COMPANY-SYSTEM
262
263where SYSTEM can have one of these forms:
264
265 OS
266 KERNEL-OS
267
268 See the file `config.sub' for the possible values of each field. If
269`config.sub' isn't included in this package, then this package doesn't
270need to know the machine type.
271
272 If you are _building_ compiler tools for cross-compiling, you should
273use the option `--target=TYPE' to select the type of system they will
274produce code for.
275
276 If you want to _use_ a cross compiler, that generates code for a
277platform different from the build platform, you should specify the
278"host" platform (i.e., that on which the generated programs will
279eventually be run) with `--host=TYPE'.
280
281Sharing Defaults
282================
283
284 If you want to set default values for `configure' scripts to share,
285you can create a site shell script called `config.site' that gives
286default values for variables like `CC', `cache_file', and `prefix'.
287`configure' looks for `PREFIX/share/config.site' if it exists, then
288`PREFIX/etc/config.site' if it exists. Or, you can set the
289`CONFIG_SITE' environment variable to the location of the site script.
290A warning: not all `configure' scripts look for a site script.
291
292Defining Variables
293==================
294
295 Variables not defined in a site shell script can be set in the
296environment passed to `configure'. However, some packages may run
297configure again during the build, and the customized values of these
298variables may be lost. In order to avoid this problem, you should set
299them in the `configure' command line, using `VAR=value'. For example:
300
301 ./configure CC=/usr/local2/bin/gcc
302
303causes the specified `gcc' to be used as the C compiler (unless it is
304overridden in the site shell script).
305
306Unfortunately, this technique does not work for `CONFIG_SHELL' due to
307an Autoconf bug. Until the bug is fixed you can use this workaround:
308
309 CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
310
311`configure' Invocation
312======================
313
314 `configure' recognizes the following options to control how it
315operates.
316
317`--help'
318`-h'
319 Print a summary of all of the options to `configure', and exit.
320
321`--help=short'
322`--help=recursive'
323 Print a summary of the options unique to this package's
324 `configure', and exit. The `short' variant lists options used
325 only in the top level, while the `recursive' variant lists options
326 also present in any nested packages.
327
328`--version'
329`-V'
330 Print the version of Autoconf used to generate the `configure'
331 script, and exit.
332
333`--cache-file=FILE'
334 Enable the cache: use and save the results of the tests in FILE,
335 traditionally `config.cache'. FILE defaults to `/dev/null' to
336 disable caching.
337
338`--config-cache'
339`-C'
340 Alias for `--cache-file=config.cache'.
341
342`--quiet'
343`--silent'
344`-q'
345 Do not print messages saying which checks are being made. To
346 suppress all normal output, redirect it to `/dev/null' (any error
347 messages will still be shown).
348
349`--srcdir=DIR'
350 Look for the package's source code in directory DIR. Usually
351 `configure' can determine that directory automatically.
352
353`--prefix=DIR'
354 Use DIR as the installation prefix. *note Installation Names::
355 for more details, including other options available for fine-tuning
356 the installation locations.
357
358`--no-create'
359`-n'
360 Run the configure checks, but stop before creating any output
361 files.
362
363`configure' also accepts some other, not widely useful, options. Run
364`configure --help' for more details.
365
diff --git a/pathologist/Makefile.am b/pathologist/Makefile.am
new file mode 100644
index 0000000..acbfe9c
--- /dev/null
+++ b/pathologist/Makefile.am
@@ -0,0 +1,11 @@
1## Process this file with automake to produce Makefile.in
2
3SUBDIRS = refs/src src
4
5EXTRA_DIST = \
6 ABOUT-NLS \
7 config.rpath \
8 install-sh \
9 acinclude.m4
10
11ACLOCAL_AMFLAGS = -I m4
diff --git a/pathologist/NEWS b/pathologist/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pathologist/NEWS
diff --git a/pathologist/README b/pathologist/README
new file mode 100644
index 0000000..a166810
--- /dev/null
+++ b/pathologist/README
@@ -0,0 +1 @@
This is a template for GNUnet extensions.
diff --git a/pathologist/bootstrap b/pathologist/bootstrap
new file mode 100755
index 0000000..c5d2098
--- /dev/null
+++ b/pathologist/bootstrap
@@ -0,0 +1,8 @@
1#!/bin/sh
2
3libtoolize --automake --copy --force
4aclocal -I m4
5autoheader
6autoconf
7automake --add-missing --copy
8
diff --git a/pathologist/config.rpath b/pathologist/config.rpath
new file mode 100755
index 0000000..c547c68
--- /dev/null
+++ b/pathologist/config.rpath
@@ -0,0 +1,666 @@
1#! /bin/sh
2# Output a system dependent set of variables, describing how to set the
3# run time search path of shared libraries in an executable.
4#
5# Copyright 1996-2007 Free Software Foundation, Inc.
6# Taken from GNU libtool, 2001
7# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
8#
9# This file is free software; the Free Software Foundation gives
10# unlimited permission to copy and/or distribute it, with or without
11# modifications, as long as this notice is preserved.
12#
13# The first argument passed to this file is the canonical host specification,
14# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
15# or
16# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
17# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
18# should be set by the caller.
19#
20# The set of defined variables is at the end of this script.
21
22# Known limitations:
23# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
24# than 256 bytes, otherwise the compiler driver will dump core. The only
25# known workaround is to choose shorter directory names for the build
26# directory and/or the installation directory.
27
28# All known linkers require a `.a' archive for static linking (except MSVC,
29# which needs '.lib').
30libext=a
31shrext=.so
32
33host="$1"
34host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
35host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
36host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
37
38# Code taken from libtool.m4's _LT_CC_BASENAME.
39
40for cc_temp in $CC""; do
41 case $cc_temp in
42 compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
43 distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
44 \-*) ;;
45 *) break;;
46 esac
47done
48cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
49
50# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
51
52wl=
53if test "$GCC" = yes; then
54 wl='-Wl,'
55else
56 case "$host_os" in
57 aix*)
58 wl='-Wl,'
59 ;;
60 darwin*)
61 case $cc_basename in
62 xlc*)
63 wl='-Wl,'
64 ;;
65 esac
66 ;;
67 mingw* | cygwin* | pw32* | os2*)
68 ;;
69 hpux9* | hpux10* | hpux11*)
70 wl='-Wl,'
71 ;;
72 irix5* | irix6* | nonstopux*)
73 wl='-Wl,'
74 ;;
75 newsos6)
76 ;;
77 linux* | k*bsd*-gnu)
78 case $cc_basename in
79 icc* | ecc*)
80 wl='-Wl,'
81 ;;
82 pgcc | pgf77 | pgf90)
83 wl='-Wl,'
84 ;;
85 ccc*)
86 wl='-Wl,'
87 ;;
88 como)
89 wl='-lopt='
90 ;;
91 *)
92 case `$CC -V 2>&1 | sed 5q` in
93 *Sun\ C*)
94 wl='-Wl,'
95 ;;
96 esac
97 ;;
98 esac
99 ;;
100 osf3* | osf4* | osf5*)
101 wl='-Wl,'
102 ;;
103 rdos*)
104 ;;
105 solaris*)
106 wl='-Wl,'
107 ;;
108 sunos4*)
109 wl='-Qoption ld '
110 ;;
111 sysv4 | sysv4.2uw2* | sysv4.3*)
112 wl='-Wl,'
113 ;;
114 sysv4*MP*)
115 ;;
116 sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
117 wl='-Wl,'
118 ;;
119 unicos*)
120 wl='-Wl,'
121 ;;
122 uts4*)
123 ;;
124 esac
125fi
126
127# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
128
129hardcode_libdir_flag_spec=
130hardcode_libdir_separator=
131hardcode_direct=no
132hardcode_minus_L=no
133
134case "$host_os" in
135 cygwin* | mingw* | pw32*)
136 # FIXME: the MSVC++ port hasn't been tested in a loooong time
137 # When not using gcc, we currently assume that we are using
138 # Microsoft Visual C++.
139 if test "$GCC" != yes; then
140 with_gnu_ld=no
141 fi
142 ;;
143 interix*)
144 # we just hope/assume this is gcc and not c89 (= MSVC++)
145 with_gnu_ld=yes
146 ;;
147 openbsd*)
148 with_gnu_ld=no
149 ;;
150esac
151
152ld_shlibs=yes
153if test "$with_gnu_ld" = yes; then
154 # Set some defaults for GNU ld with shared library support. These
155 # are reset later if shared libraries are not supported. Putting them
156 # here allows them to be overridden if necessary.
157 # Unlike libtool, we use -rpath here, not --rpath, since the documented
158 # option of GNU ld is called -rpath, not --rpath.
159 hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
160 case "$host_os" in
161 aix3* | aix4* | aix5*)
162 # On AIX/PPC, the GNU linker is very broken
163 if test "$host_cpu" != ia64; then
164 ld_shlibs=no
165 fi
166 ;;
167 amigaos*)
168 hardcode_libdir_flag_spec='-L$libdir'
169 hardcode_minus_L=yes
170 # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
171 # that the semantics of dynamic libraries on AmigaOS, at least up
172 # to version 4, is to share data among multiple programs linked
173 # with the same dynamic library. Since this doesn't match the
174 # behavior of shared libraries on other platforms, we cannot use
175 # them.
176 ld_shlibs=no
177 ;;
178 beos*)
179 if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
180 :
181 else
182 ld_shlibs=no
183 fi
184 ;;
185 cygwin* | mingw* | pw32*)
186 # hardcode_libdir_flag_spec is actually meaningless, as there is
187 # no search path for DLLs.
188 hardcode_libdir_flag_spec='-L$libdir'
189 if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
190 :
191 else
192 ld_shlibs=no
193 fi
194 ;;
195 interix[3-9]*)
196 hardcode_direct=no
197 hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
198 ;;
199 gnu* | linux* | k*bsd*-gnu)
200 if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
201 :
202 else
203 ld_shlibs=no
204 fi
205 ;;
206 netbsd*)
207 ;;
208 solaris*)
209 if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
210 ld_shlibs=no
211 elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
212 :
213 else
214 ld_shlibs=no
215 fi
216 ;;
217 sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
218 case `$LD -v 2>&1` in
219 *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
220 ld_shlibs=no
221 ;;
222 *)
223 if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
224 hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
225 else
226 ld_shlibs=no
227 fi
228 ;;
229 esac
230 ;;
231 sunos4*)
232 hardcode_direct=yes
233 ;;
234 *)
235 if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
236 :
237 else
238 ld_shlibs=no
239 fi
240 ;;
241 esac
242 if test "$ld_shlibs" = no; then
243 hardcode_libdir_flag_spec=
244 fi
245else
246 case "$host_os" in
247 aix3*)
248 # Note: this linker hardcodes the directories in LIBPATH if there
249 # are no directories specified by -L.
250 hardcode_minus_L=yes
251 if test "$GCC" = yes; then
252 # Neither direct hardcoding nor static linking is supported with a
253 # broken collect2.
254 hardcode_direct=unsupported
255 fi
256 ;;
257 aix4* | aix5*)
258 if test "$host_cpu" = ia64; then
259 # On IA64, the linker does run time linking by default, so we don't
260 # have to do anything special.
261 aix_use_runtimelinking=no
262 else
263 aix_use_runtimelinking=no
264 # Test if we are trying to use run time linking or normal
265 # AIX style linking. If -brtl is somewhere in LDFLAGS, we
266 # need to do runtime linking.
267 case $host_os in aix4.[23]|aix4.[23].*|aix5*)
268 for ld_flag in $LDFLAGS; do
269 if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
270 aix_use_runtimelinking=yes
271 break
272 fi
273 done
274 ;;
275 esac
276 fi
277 hardcode_direct=yes
278 hardcode_libdir_separator=':'
279 if test "$GCC" = yes; then
280 case $host_os in aix4.[012]|aix4.[012].*)
281 collect2name=`${CC} -print-prog-name=collect2`
282 if test -f "$collect2name" && \
283 strings "$collect2name" | grep resolve_lib_name >/dev/null
284 then
285 # We have reworked collect2
286 :
287 else
288 # We have old collect2
289 hardcode_direct=unsupported
290 hardcode_minus_L=yes
291 hardcode_libdir_flag_spec='-L$libdir'
292 hardcode_libdir_separator=
293 fi
294 ;;
295 esac
296 fi
297 # Begin _LT_AC_SYS_LIBPATH_AIX.
298 echo 'int main () { return 0; }' > conftest.c
299 ${CC} ${LDFLAGS} conftest.c -o conftest
300 aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
301}'`
302 if test -z "$aix_libpath"; then
303 aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
304}'`
305 fi
306 if test -z "$aix_libpath"; then
307 aix_libpath="/usr/lib:/lib"
308 fi
309 rm -f conftest.c conftest
310 # End _LT_AC_SYS_LIBPATH_AIX.
311 if test "$aix_use_runtimelinking" = yes; then
312 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
313 else
314 if test "$host_cpu" = ia64; then
315 hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
316 else
317 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
318 fi
319 fi
320 ;;
321 amigaos*)
322 hardcode_libdir_flag_spec='-L$libdir'
323 hardcode_minus_L=yes
324 # see comment about different semantics on the GNU ld section
325 ld_shlibs=no
326 ;;
327 bsdi[45]*)
328 ;;
329 cygwin* | mingw* | pw32*)
330 # When not using gcc, we currently assume that we are using
331 # Microsoft Visual C++.
332 # hardcode_libdir_flag_spec is actually meaningless, as there is
333 # no search path for DLLs.
334 hardcode_libdir_flag_spec=' '
335 libext=lib
336 ;;
337 darwin* | rhapsody*)
338 hardcode_direct=no
339 if test "$GCC" = yes ; then
340 :
341 else
342 case $cc_basename in
343 xlc*)
344 ;;
345 *)
346 ld_shlibs=no
347 ;;
348 esac
349 fi
350 ;;
351 dgux*)
352 hardcode_libdir_flag_spec='-L$libdir'
353 ;;
354 freebsd1*)
355 ld_shlibs=no
356 ;;
357 freebsd2.2*)
358 hardcode_libdir_flag_spec='-R$libdir'
359 hardcode_direct=yes
360 ;;
361 freebsd2*)
362 hardcode_direct=yes
363 hardcode_minus_L=yes
364 ;;
365 freebsd* | dragonfly*)
366 hardcode_libdir_flag_spec='-R$libdir'
367 hardcode_direct=yes
368 ;;
369 hpux9*)
370 hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
371 hardcode_libdir_separator=:
372 hardcode_direct=yes
373 # hardcode_minus_L: Not really in the search PATH,
374 # but as the default location of the library.
375 hardcode_minus_L=yes
376 ;;
377 hpux10*)
378 if test "$with_gnu_ld" = no; then
379 hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
380 hardcode_libdir_separator=:
381 hardcode_direct=yes
382 # hardcode_minus_L: Not really in the search PATH,
383 # but as the default location of the library.
384 hardcode_minus_L=yes
385 fi
386 ;;
387 hpux11*)
388 if test "$with_gnu_ld" = no; then
389 hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
390 hardcode_libdir_separator=:
391 case $host_cpu in
392 hppa*64*|ia64*)
393 hardcode_direct=no
394 ;;
395 *)
396 hardcode_direct=yes
397 # hardcode_minus_L: Not really in the search PATH,
398 # but as the default location of the library.
399 hardcode_minus_L=yes
400 ;;
401 esac
402 fi
403 ;;
404 irix5* | irix6* | nonstopux*)
405 hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
406 hardcode_libdir_separator=:
407 ;;
408 netbsd*)
409 hardcode_libdir_flag_spec='-R$libdir'
410 hardcode_direct=yes
411 ;;
412 newsos6)
413 hardcode_direct=yes
414 hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
415 hardcode_libdir_separator=:
416 ;;
417 openbsd*)
418 if test -f /usr/libexec/ld.so; then
419 hardcode_direct=yes
420 if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
421 hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
422 else
423 case "$host_os" in
424 openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
425 hardcode_libdir_flag_spec='-R$libdir'
426 ;;
427 *)
428 hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
429 ;;
430 esac
431 fi
432 else
433 ld_shlibs=no
434 fi
435 ;;
436 os2*)
437 hardcode_libdir_flag_spec='-L$libdir'
438 hardcode_minus_L=yes
439 ;;
440 osf3*)
441 hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
442 hardcode_libdir_separator=:
443 ;;
444 osf4* | osf5*)
445 if test "$GCC" = yes; then
446 hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
447 else
448 # Both cc and cxx compiler support -rpath directly
449 hardcode_libdir_flag_spec='-rpath $libdir'
450 fi
451 hardcode_libdir_separator=:
452 ;;
453 solaris*)
454 hardcode_libdir_flag_spec='-R$libdir'
455 ;;
456 sunos4*)
457 hardcode_libdir_flag_spec='-L$libdir'
458 hardcode_direct=yes
459 hardcode_minus_L=yes
460 ;;
461 sysv4)
462 case $host_vendor in
463 sni)
464 hardcode_direct=yes # is this really true???
465 ;;
466 siemens)
467 hardcode_direct=no
468 ;;
469 motorola)
470 hardcode_direct=no #Motorola manual says yes, but my tests say they lie
471 ;;
472 esac
473 ;;
474 sysv4.3*)
475 ;;
476 sysv4*MP*)
477 if test -d /usr/nec; then
478 ld_shlibs=yes
479 fi
480 ;;
481 sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
482 ;;
483 sysv5* | sco3.2v5* | sco5v6*)
484 hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
485 hardcode_libdir_separator=':'
486 ;;
487 uts4*)
488 hardcode_libdir_flag_spec='-L$libdir'
489 ;;
490 *)
491 ld_shlibs=no
492 ;;
493 esac
494fi
495
496# Check dynamic linker characteristics
497# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
498# Unlike libtool.m4, here we don't care about _all_ names of the library, but
499# only about the one the linker finds when passed -lNAME. This is the last
500# element of library_names_spec in libtool.m4, or possibly two of them if the
501# linker has special search rules.
502library_names_spec= # the last element of library_names_spec in libtool.m4
503libname_spec='lib$name'
504case "$host_os" in
505 aix3*)
506 library_names_spec='$libname.a'
507 ;;
508 aix4* | aix5*)
509 library_names_spec='$libname$shrext'
510 ;;
511 amigaos*)
512 library_names_spec='$libname.a'
513 ;;
514 beos*)
515 library_names_spec='$libname$shrext'
516 ;;
517 bsdi[45]*)
518 library_names_spec='$libname$shrext'
519 ;;
520 cygwin* | mingw* | pw32*)
521 shrext=.dll
522 library_names_spec='$libname.dll.a $libname.lib'
523 ;;
524 darwin* | rhapsody*)
525 shrext=.dylib
526 library_names_spec='$libname$shrext'
527 ;;
528 dgux*)
529 library_names_spec='$libname$shrext'
530 ;;
531 freebsd1*)
532 ;;
533 freebsd* | dragonfly*)
534 case "$host_os" in
535 freebsd[123]*)
536 library_names_spec='$libname$shrext$versuffix' ;;
537 *)
538 library_names_spec='$libname$shrext' ;;
539 esac
540 ;;
541 gnu*)
542 library_names_spec='$libname$shrext'
543 ;;
544 hpux9* | hpux10* | hpux11*)
545 case $host_cpu in
546 ia64*)
547 shrext=.so
548 ;;
549 hppa*64*)
550 shrext=.sl
551 ;;
552 *)
553 shrext=.sl
554 ;;
555 esac
556 library_names_spec='$libname$shrext'
557 ;;
558 interix[3-9]*)
559 library_names_spec='$libname$shrext'
560 ;;
561 irix5* | irix6* | nonstopux*)
562 library_names_spec='$libname$shrext'
563 case "$host_os" in
564 irix5* | nonstopux*)
565 libsuff= shlibsuff=
566 ;;
567 *)
568 case $LD in
569 *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
570 *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
571 *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
572 *) libsuff= shlibsuff= ;;
573 esac
574 ;;
575 esac
576 ;;
577 linux*oldld* | linux*aout* | linux*coff*)
578 ;;
579 linux* | k*bsd*-gnu)
580 library_names_spec='$libname$shrext'
581 ;;
582 knetbsd*-gnu)
583 library_names_spec='$libname$shrext'
584 ;;
585 netbsd*)
586 library_names_spec='$libname$shrext'
587 ;;
588 newsos6)
589 library_names_spec='$libname$shrext'
590 ;;
591 nto-qnx*)
592 library_names_spec='$libname$shrext'
593 ;;
594 openbsd*)
595 library_names_spec='$libname$shrext$versuffix'
596 ;;
597 os2*)
598 libname_spec='$name'
599 shrext=.dll
600 library_names_spec='$libname.a'
601 ;;
602 osf3* | osf4* | osf5*)
603 library_names_spec='$libname$shrext'
604 ;;
605 rdos*)
606 ;;
607 solaris*)
608 library_names_spec='$libname$shrext'
609 ;;
610 sunos4*)
611 library_names_spec='$libname$shrext$versuffix'
612 ;;
613 sysv4 | sysv4.3*)
614 library_names_spec='$libname$shrext'
615 ;;
616 sysv4*MP*)
617 library_names_spec='$libname$shrext'
618 ;;
619 sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
620 library_names_spec='$libname$shrext'
621 ;;
622 uts4*)
623 library_names_spec='$libname$shrext'
624 ;;
625esac
626
627sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
628escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
629shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
630escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
631escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
632escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
633
634LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
635
636# How to pass a linker flag through the compiler.
637wl="$escaped_wl"
638
639# Static library suffix (normally "a").
640libext="$libext"
641
642# Shared library suffix (normally "so").
643shlibext="$shlibext"
644
645# Format of library name prefix.
646libname_spec="$escaped_libname_spec"
647
648# Library names that the linker finds when passed -lNAME.
649library_names_spec="$escaped_library_names_spec"
650
651# Flag to hardcode \$libdir into a binary during linking.
652# This must work even if \$libdir does not exist.
653hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
654
655# Whether we need a single -rpath flag with a separated argument.
656hardcode_libdir_separator="$hardcode_libdir_separator"
657
658# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
659# resulting binary.
660hardcode_direct="$hardcode_direct"
661
662# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
663# resulting binary.
664hardcode_minus_L="$hardcode_minus_L"
665
666EOF
diff --git a/pathologist/configure.ac b/pathologist/configure.ac
new file mode 100644
index 0000000..0f63f2e
--- /dev/null
+++ b/pathologist/configure.ac
@@ -0,0 +1,221 @@
1# This file is part of GNUnet.
2# (C) 2001-2012 Christian Grothoff (and other contributing authors)
3#
4# GNUnet is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published
6# by the Free Software Foundation; either version 2, or (at your
7# option) any later version.
8#
9# GNUnet is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12# General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with GNUnet; see the file COPYING. If not, write to the
16# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17# Boston, MA 02111-1307, USA.
18#
19#
20# Process this file with autoconf to produce a configure script.
21#
22AC_PREREQ(2.61)
23AC_INIT([monkey],[0.0.0],[bug-gnunet@gnu.org])
24AM_INIT_AUTOMAKE([monkey], [0.0.0])
25AM_CONFIG_HEADER(monkey_config.h)
26
27AH_TOP([#define _GNU_SOURCE 1])
28
29AC_ISC_POSIX
30AC_PROG_AWK
31AC_PROG_CC
32
33AC_PROG_MKDIR_P
34AC_PROG_CPP
35AC_PROG_INSTALL
36AC_PROG_LN_S
37AC_PROG_MAKE_SET
38AC_LIBTOOL_WIN32_DLL
39AC_PROG_CC
40AM_PROG_CC_STDC
41AC_HEADER_STDC
42AC_CANONICAL_HOST
43
44# dynamic libraries/plugins
45AC_DISABLE_STATIC
46AC_PROG_LIBTOOL
47
48AC_SYS_LARGEFILE
49AC_FUNC_FSEEKO
50
51CFLAGS="-Wall $CFLAGS"
52# use '-fno-strict-aliasing', but only if the compiler can take it
53if gcc -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1;
54then
55 CFLAGS="-fno-strict-aliasing $CFLAGS"
56fi
57
58
59# Check system type
60case "$host_os" in
61*darwin* | *rhapsody* | *macosx*)
62 AC_DEFINE_UNQUOTED(OSX,1,[This is an OS X system])
63 CFLAGS="-no-cpp-precomp $CFLAGS"
64 LDFLAGS="-flat_namespace -undefined suppress $LDFLAGS"
65 ;;
66linux*)
67 AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
68 ;;
69freebsd*)
70 AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
71 AC_DEFINE_UNQUOTED(FREEBSD,1,[This is a FreeBSD system])
72 ;;
73openbsd*)
74 AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
75 AC_DEFINE_UNQUOTED(OPENBSD,1,[This is an OpenBSD system])
76 ;;
77netbsd*)
78 AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
79 AC_DEFINE_UNQUOTED(NETBSD,1,[This is a NetBSD system])
80 ;;
81*solaris*)
82 AC_DEFINE_UNQUOTED(SOLARIS,1,[This is a Solaris system])
83 AC_DEFINE_UNQUOTED(_REENTRANT,1,[Need with solaris or errno doesnt work])
84 build_target="solaris"
85 ;;
86*arm-linux*)
87 AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
88 ;;
89*cygwin*)
90 AC_DEFINE_UNQUOTED(CYGWIN,1,[This is a Cygwin system])
91 AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
92 AC_CHECK_LIB(intl, gettext)
93 LDFLAGS="$LDFLAGS -no-undefined"
94 build_target="cygwin"
95 ;;
96*mingw*)
97 AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system])
98 AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
99 AC_DEFINE_UNQUOTED(_WIN32,1,[This is a Windows system])
100 AC_CHECK_LIB(intl, gettext)
101 LDFLAGS="$LDFLAGS -no-undefined -Wl,--export-all-symbols -lws2_32"
102 CFLAGS="-mms-bitfields $CFLAGS"
103 build_target="mingw"
104 ;;
105*)
106 AC_MSG_RESULT(Unrecognised OS $host_os)
107 AC_DEFINE_UNQUOTED(OTHEROS,1,[Some strange OS])
108;;
109esac
110
111AM_CONDITIONAL(MINGW, test "$build_target" = "mingw")
112
113AC_CHECK_HEADERS([errno.h stdio.h unistd.h locale.h sys/stat.h sys/types.h langinfo.h libintl.h unistd.h stddef.h argz.h sys/socket.h netinet/in.h stdarg.h])
114
115# openssl
116openssl=0
117AC_MSG_CHECKING([for openssl])
118AC_ARG_WITH(openssl,
119 [ --with-openssl=PFX base of openssl installation],
120 [AC_MSG_RESULT([$with_openssl])
121 case $with_openssl in
122 no)
123 ;;
124 yes)
125 AC_CHECK_HEADERS([openssl/ssl.h],
126 AC_CHECK_LIB([ssl], [SSL_new],
127 openssl=1))
128 ;;
129 *)
130 LDFLAGS="-L$with_openssl/lib $LDFLAGS"
131 CPPFLAGS="-I$with_openssl/include $CPPFLAGS"
132 AC_CHECK_HEADERS([openssl/ssl.h],
133 AC_CHECK_LIB([ssl], [SSL_new],
134 EXT_LIB_PATH="-L$with_openssl/lib $EXT_LIB_PATH"
135 openssl=1))
136 ;;
137 esac
138 ],
139 [AC_MSG_RESULT([--with-openssl not specified])
140 AC_CHECK_HEADERS([openssl/ssl.h],
141 AC_CHECK_LIB([ssl], [SSL_new],
142 openssl=1))])
143AM_CONDITIONAL(HAVE_OPENSSL, test x$openssl = x1)
144AC_DEFINE_UNQUOTED([HAVE_OPENSSL], $openssl, [We have openssl])
145
146
147
148# libesmtp
149esmtp=0
150AC_MSG_CHECKING([for libesmtp])
151AC_ARG_WITH(esmtp,
152 [ --with-esmtp=PFX base of libesmtp installation],
153 [AC_MSG_RESULT([$with_esmtp])
154 case $with_esmtp in
155 no)
156 ;;
157 yes)
158 AC_CHECK_HEADERS(libesmtp.h,
159 AC_CHECK_LIB([esmtp], [smtp_start_session],
160 esmtp=1))
161 ;;
162 *)
163 LDFLAGS="-L$with_esmtp/lib $LDFLAGS"
164 CPPFLAGS="-I$with_esmtp/include $CPPFLAGS"
165 AC_CHECK_HEADERS(libesmtp.h,
166 AC_CHECK_LIB([esmtp], [smtp_start_session],
167 EXT_LIB_PATH="-L$with_esmtp/lib $EXT_LIB_PATH"
168 esmtp=1))
169 ;;
170 esac
171 ],
172 [AC_MSG_RESULT([--with-esmtp not specified])
173 AC_CHECK_HEADERS(libesmtp.h,
174 AC_CHECK_LIB([esmtp], [smtp_start_session],
175 esmtp=1))])
176AM_CONDITIONAL(HAVE_ESMTP, test x$esmtp = x1)
177AC_DEFINE_UNQUOTED([HAVE_ESMTP], $esmtp, [We have libesmtp])
178# restore LIBS
179LIBS=$SAVE_LIBS
180
181
182# gcov compilation
183AC_MSG_CHECKING(whether to compile with support for code coverage analysis)
184AC_ARG_ENABLE([coverage],
185 AS_HELP_STRING([--enable-coverage],
186 [compile the library with code coverage support]),
187 [use_gcov=${enableval}],
188 [use_gcov=no])
189AC_MSG_RESULT($use_gcov)
190AM_CONDITIONAL([USE_COVERAGE], [test "x$use_gcov" = "xyes"])
191
192
193# should 'make check' run tests?
194AC_MSG_CHECKING(whether to run tests)
195AC_ARG_ENABLE([testruns],
196 [AS_HELP_STRING([--disable-testruns], [disable running tests on make check (default is YES)])],
197 [enable_tests_run=${enableval}],
198 [enable_tests_run=yes])
199AC_MSG_RESULT($enable_test_run)
200AM_CONDITIONAL([ENABLE_TEST_RUN], [test "x$enable_tests_run" = "xyes"])
201
202AC_CHECK_PROG(SSP_FOUND, seaspider, [yes], [no], [../seaspider/bin])
203AM_CONDITIONAL([SEASPIDER], [test "$SSP_FOUND" = yes])
204
205
206AC_DEFINE_DIR([PACKAGE_DATA], [datarootdir], [The directory for installing read-only architecture-independent data])
207
208# Set PACKAGE_SOURCE_DIR in gnunet_gtk_config.h.
209packagesrcdir=`cd $srcdir && pwd`
210AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}", [source dir])
211
212AC_OUTPUT([
213Makefile
214src/Makefile
215src/include/Makefile
216src/mi/Makefile
217src/minixml/Makefile
218src/util/Makefile
219src/pathologist/Makefile
220refs/src/Makefile
221])
diff --git a/pathologist/contrib/monkey_sysinfo.sh b/pathologist/contrib/monkey_sysinfo.sh
new file mode 100755
index 0000000..d5c7866
--- /dev/null
+++ b/pathologist/contrib/monkey_sysinfo.sh
@@ -0,0 +1,228 @@
1#!/bin/sh
2
3TEST=`type type|grep not`
4if test -n "$TEST"; then
5 WHICH=which
6else
7 WHICH=type
8fi
9
10echo "\t<sysinfo>"
11OS=`uname -s 2>/dev/null`
12echo "\t\t<os>$OS</os>"
13REL=`uname -r 2>/dev/null`
14echo "\t\t<os_release>$REL</os_release>"
15HW=`uname -m 2>/dev/null`
16echo "\t\t<hardware>$HW</hardware>"
17
18TEST=`$WHICH gcc 2>/dev/null`
19if test -n "$TEST"; then
20 VERS=`gcc --version 2>/dev/null | head -n 1`
21 echo "gcc : $VERS"
22else
23 echo "gcc : Not Found";
24fi
25
26TEST=`$WHICH gmake 2>/dev/null`
27if test -n "$TEST" ; then
28 gmake --version 2>/dev/null |\
29 awk -F, '{print $1}' |\
30 awk '/GNU Make/{print "GNU gmake :",$NF}'
31else
32 TEST=`make --version 2>/dev/null`
33 if test -n "$TEST"; then
34 make --version 2>/dev/null |\
35 awk -F, '{print $1}' |\
36 awk '/GNU Make/{print "make :",$NF}'
37 else
38 echo "make : Not Found"
39 fi
40fi
41
42TEST=`$WHICH autoconf 2>/dev/null`
43if test -n "$TEST"; then
44 autoconf --version |\
45 head -n 1 |\
46 awk '{\
47 if (length($4) == 0) {\
48 print "autoconf : "$3\
49 } else {\
50 print "autoconf : "$4\
51 }}'
52else
53 echo "autoconf : Not Found"
54fi
55
56TEST=`$WHICH automake 2>/dev/null`
57if test -n "$TEST"; then
58 automake --version 2>/dev/null |\
59 head -n 1 |\
60 awk '{print "automake : "$4}'
61else
62 echo "automake : Not Found"
63fi
64
65TEST=`$WHICH libtool 2>/dev/null`
66if test -n "$TEST"; then
67 libtool --version 2>/dev/null |\
68 head -n 1 |\
69 awk '{print "libtool : "$4}'
70else
71 echo "libtool : Not Found"
72fi
73
74TEST=`$WHICH extract 2>/dev/null`
75if test -n "$TEST"; then
76 extract -v 2>/dev/null |\
77 head -n 1 |\
78 awk '{print "libextractor : "$2}'
79else
80 echo "libextractor : Not Found"
81fi
82
83TEST=`$WHICH libgcrypt-config 2> /dev/null`
84if test -n "$TEST"; then
85 libgcrypt-config --version 2> /dev/null | \
86 awk '{print "libgcrypt : "$1}'
87else
88 echo "libgcrypt : Not Found"
89fi
90
91TEST=`$WHICH mysql_config 2> /dev/null`
92if test -n "$TEST"; then
93 mysql_config --version 2> /dev/null | \
94 awk '{print "mysql : "$1}'
95else
96 echo "mysql : Not Found"
97fi
98
99TEST=`$WHICH pkg-config 2> /dev/null`
100if test -n "$TEST"; then
101 pkg-config --version 2> /dev/null | \
102 awk '{print "pkg-config : "$1}'
103else
104 echo "pkg-config : Not Found"
105fi
106
107TEST=`$WHICH pkg-config 2> /dev/null`
108if test -n "$TEST"; then
109 pkg-config --modversion glib-2.0 2> /dev/null | \
110 awk '{print "glib2 : "$1}'
111else
112 echo "glib2 : Not Found"
113fi
114
115TEST=`$WHICH pkg-config 2> /dev/null`
116if test -n "$TEST"; then
117 pkg-config --modversion gtk+-2.0 2> /dev/null | \
118 awk '{print "gtk2+ : "$1}'
119else
120 echo "gtk2+ : Not Found"
121fi
122
123TEST=`$WHICH dpkg 2> /dev/null`
124if test -n "$TEST"; then
125 LINES=`dpkg -s libgmp3-dev | grep Version | wc -l`
126 if test "$LINES" = "1"
127 then
128 VERSION=`dpkg -s libgmp3-dev | grep Version | awk '{print $2}'`
129 echo "GMP : libgmp3-dev-$VERSION.deb"
130 else
131 echo "GMP : dpkg: libgmp3-dev not installed"
132 fi
133else
134 TEST=`$WHICH rpm 2> /dev/null`
135 if test -n "$TEST"; then
136 rpm -q gmp | sed -e "s/gmp-//" 2> /dev/null | \
137 awk '{print "GMP : "$1.rpm}'
138 else
139 echo "GMP : Test not available"
140 fi
141fi
142
143TEST=`$WHICH dpkg 2> /dev/null`
144if test -n "$TEST"; then
145 LINES=`dpkg -s libunistring-dev | grep Version | wc -l`
146 if test "$LINES" = "1"
147 then
148 VERSION=`dpkg -s libunistring-dev | grep Version | awk '{print $2}'`
149 echo "libunistring : libunistring3-dev-$VERSION.deb"
150 else
151 echo "libunistring : dpkg: libunistring3-dev not installed"
152 fi
153else
154 TEST=`$WHICH rpm 2> /dev/null`
155 if test -n "$TEST"; then
156 rpm -q unistring | sed -e "s/unistring-//" 2> /dev/null | \
157 awk '{print "libunistring : "$1.rpm}'
158 else
159 echo "libunistring : Test not available"
160 fi
161fi
162
163TEST=`$WHICH gettext 2> /dev/null`
164if test -n "$TEST"; then
165 gettext --version | head -n1 2> /dev/null | \
166 awk '{print "GNU gettext : "$4}'
167else
168 echo "GNU gettext : Not found"
169fi
170
171
172TEST=`$WHICH curl-config 2> /dev/null`
173if test -n "$TEST"; then
174 curl-config --version | head -n1 2> /dev/null | \
175 awk '{print "libcurl : "$2}'
176else
177 echo "libcurl : Not found"
178fi
179
180echo -n "libmicrohttpd : "
181TMPFILE=`mktemp /tmp/mhd-version-testXXXXXX`
182cat - >$TMPFILE.c <<EOF
183#include <microhttpd.h>
184#include <stdio.h>
185int main()
186{
187 fprintf (stdout, "%X\n", MHD_VERSION);
188 return 0;
189}
190EOF
191
192gcc -o $TMPFILE $TMPFILE.c 2> /dev/null && $TMPFILE || echo "Not found"
193rm -f $TMPFILE $TMPFILE.bin
194
195
196echo -n "GNU GLPK : "
197TMPFILE=`mktemp /tmp/glpk-version-testXXXXXX`
198cat - >$TMPFILE.c <<EOF
199#include <glpk.h>
200#include <stdio.h>
201int main()
202{
203 fprintf (stdout, "%u.%u\n", GLP_MAJOR_VERSION, GLP_MINOR_VERSION);
204 return 0;
205}
206EOF
207
208gcc -o $TMPFILE $TMPFILE.c 2> /dev/null && $TMPFILE || echo "Not found"
209rm -f $TMPFILE $TMPFILE.bin
210
211
212echo -n "GNUtls : "
213TMPFILE=`mktemp /tmp/gnutls-version-testXXXXXX`
214cat - >$TMPFILE.c <<EOF
215#include <gnutls/gnutls.h>
216#include <stdio.h>
217int main()
218{
219 fprintf (stdout, "%s\n", GNUTLS_VERSION);
220 return 0;
221}
222EOF
223
224gcc -o $TMPFILE $TMPFILE.c 2> /dev/null && $TMPFILE || echo "Not found"
225rm -f $TMPFILE $TMPFILE.bin
226
227
228echo "\t</sysinfo>"
diff --git a/pathologist/m4/ac_define_dir.m4 b/pathologist/m4/ac_define_dir.m4
new file mode 100644
index 0000000..f7e028f
--- /dev/null
+++ b/pathologist/m4/ac_define_dir.m4
@@ -0,0 +1,35 @@
1dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
2dnl
3dnl This macro _AC_DEFINEs VARNAME to the expansion of the DIR
4dnl variable, taking care of fixing up ${prefix} and such.
5dnl
6dnl VARNAME is offered as both a C preprocessor symbol, and an output
7dnl variable.
8dnl
9dnl Note that the 3 argument form is only supported with autoconf 2.13
10dnl and later (i.e. only where _AC_DEFINE supports 3 arguments).
11dnl
12dnl Examples:
13dnl
14dnl AC_DEFINE_DIR(DATADIR, datadir)
15dnl AC_DEFINE_DIR(PROG_PATH, bindir, [Location of installed binaries])
16dnl
17dnl @category Misc
18dnl @author Stepan Kasal <kasal@ucw.cz>
19dnl @author Andreas Schwab <schwab@suse.de>
20dnl @author Guido Draheim <guidod@gmx.de>
21dnl @author Alexandre Oliva
22dnl @version 2005-01-17
23dnl @license AllPermissive
24
25AC_DEFUN([AC_DEFINE_DIR], [
26 prefix_NONE=
27 exec_prefix_NONE=
28 test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
29 test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
30 eval ac_define_dir="\"[$]$2\""
31 AC_SUBST($1, "$ac_define_dir")
32 AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
33 test "$prefix_NONE" && prefix=NONE
34 test "$exec_prefix_NONE" && exec_prefix=NONE
35])
diff --git a/pathologist/m4/libtool.m4 b/pathologist/m4/libtool.m4
new file mode 100644
index 0000000..a3fee53
--- /dev/null
+++ b/pathologist/m4/libtool.m4
@@ -0,0 +1,7377 @@
1# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
2#
3# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
4# 2006, 2007, 2008 Free Software Foundation, Inc.
5# Written by Gordon Matzigkeit, 1996
6#
7# This file is free software; the Free Software Foundation gives
8# unlimited permission to copy and/or distribute it, with or without
9# modifications, as long as this notice is preserved.
10
11m4_define([_LT_COPYING], [dnl
12# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
13# 2006, 2007, 2008 Free Software Foundation, Inc.
14# Written by Gordon Matzigkeit, 1996
15#
16# This file is part of GNU Libtool.
17#
18# GNU Libtool is free software; you can redistribute it and/or
19# modify it under the terms of the GNU General Public License as
20# published by the Free Software Foundation; either version 2 of
21# the License, or (at your option) any later version.
22#
23# As a special exception to the GNU General Public License,
24# if you distribute this file as part of a program or library that
25# is built using GNU Libtool, you may include this file under the
26# same distribution terms that you use for the rest of that program.
27#
28# GNU Libtool is distributed in the hope that it will be useful,
29# but WITHOUT ANY WARRANTY; without even the implied warranty of
30# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31# GNU General Public License for more details.
32#
33# You should have received a copy of the GNU General Public License
34# along with GNU Libtool; see the file COPYING. If not, a copy
35# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
36# obtained by writing to the Free Software Foundation, Inc.,
37# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
38])
39
40# serial 56 LT_INIT
41
42
43# LT_PREREQ(VERSION)
44# ------------------
45# Complain and exit if this libtool version is less that VERSION.
46m4_defun([LT_PREREQ],
47[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
48 [m4_default([$3],
49 [m4_fatal([Libtool version $1 or higher is required],
50 63)])],
51 [$2])])
52
53
54# _LT_CHECK_BUILDDIR
55# ------------------
56# Complain if the absolute build directory name contains unusual characters
57m4_defun([_LT_CHECK_BUILDDIR],
58[case `pwd` in
59 *\ * | *\ *)
60 AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
61esac
62])
63
64
65# LT_INIT([OPTIONS])
66# ------------------
67AC_DEFUN([LT_INIT],
68[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
69AC_BEFORE([$0], [LT_LANG])dnl
70AC_BEFORE([$0], [LT_OUTPUT])dnl
71AC_BEFORE([$0], [LTDL_INIT])dnl
72m4_require([_LT_CHECK_BUILDDIR])dnl
73
74dnl Autoconf doesn't catch unexpanded LT_ macros by default:
75m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
76m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
77dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
78dnl unless we require an AC_DEFUNed macro:
79AC_REQUIRE([LTOPTIONS_VERSION])dnl
80AC_REQUIRE([LTSUGAR_VERSION])dnl
81AC_REQUIRE([LTVERSION_VERSION])dnl
82AC_REQUIRE([LTOBSOLETE_VERSION])dnl
83m4_require([_LT_PROG_LTMAIN])dnl
84
85dnl Parse OPTIONS
86_LT_SET_OPTIONS([$0], [$1])
87
88# This can be used to rebuild libtool when needed
89LIBTOOL_DEPS="$ltmain"
90
91# Always use our own libtool.
92LIBTOOL='$(SHELL) $(top_builddir)/libtool'
93AC_SUBST(LIBTOOL)dnl
94
95_LT_SETUP
96
97# Only expand once:
98m4_define([LT_INIT])
99])# LT_INIT
100
101# Old names:
102AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
103AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
104dnl aclocal-1.4 backwards compatibility:
105dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
106dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
107
108
109# _LT_CC_BASENAME(CC)
110# -------------------
111# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
112m4_defun([_LT_CC_BASENAME],
113[for cc_temp in $1""; do
114 case $cc_temp in
115 compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
116 distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
117 \-*) ;;
118 *) break;;
119 esac
120done
121cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
122])
123
124
125# _LT_FILEUTILS_DEFAULTS
126# ----------------------
127# It is okay to use these file commands and assume they have been set
128# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
129m4_defun([_LT_FILEUTILS_DEFAULTS],
130[: ${CP="cp -f"}
131: ${MV="mv -f"}
132: ${RM="rm -f"}
133])# _LT_FILEUTILS_DEFAULTS
134
135
136# _LT_SETUP
137# ---------
138m4_defun([_LT_SETUP],
139[AC_REQUIRE([AC_CANONICAL_HOST])dnl
140AC_REQUIRE([AC_CANONICAL_BUILD])dnl
141_LT_DECL([], [host_alias], [0], [The host system])dnl
142_LT_DECL([], [host], [0])dnl
143_LT_DECL([], [host_os], [0])dnl
144dnl
145_LT_DECL([], [build_alias], [0], [The build system])dnl
146_LT_DECL([], [build], [0])dnl
147_LT_DECL([], [build_os], [0])dnl
148dnl
149AC_REQUIRE([AC_PROG_CC])dnl
150AC_REQUIRE([LT_PATH_LD])dnl
151AC_REQUIRE([LT_PATH_NM])dnl
152dnl
153AC_REQUIRE([AC_PROG_LN_S])dnl
154test -z "$LN_S" && LN_S="ln -s"
155_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
156dnl
157AC_REQUIRE([LT_CMD_MAX_LEN])dnl
158_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
159_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
160dnl
161m4_require([_LT_FILEUTILS_DEFAULTS])dnl
162m4_require([_LT_CHECK_SHELL_FEATURES])dnl
163m4_require([_LT_CMD_RELOAD])dnl
164m4_require([_LT_CHECK_MAGIC_METHOD])dnl
165m4_require([_LT_CMD_OLD_ARCHIVE])dnl
166m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
167
168_LT_CONFIG_LIBTOOL_INIT([
169# See if we are running on zsh, and set the options which allow our
170# commands through without removal of \ escapes INIT.
171if test -n "\${ZSH_VERSION+set}" ; then
172 setopt NO_GLOB_SUBST
173fi
174])
175if test -n "${ZSH_VERSION+set}" ; then
176 setopt NO_GLOB_SUBST
177fi
178
179_LT_CHECK_OBJDIR
180
181m4_require([_LT_TAG_COMPILER])dnl
182_LT_PROG_ECHO_BACKSLASH
183
184case $host_os in
185aix3*)
186 # AIX sometimes has problems with the GCC collect2 program. For some
187 # reason, if we set the COLLECT_NAMES environment variable, the problems
188 # vanish in a puff of smoke.
189 if test "X${COLLECT_NAMES+set}" != Xset; then
190 COLLECT_NAMES=
191 export COLLECT_NAMES
192 fi
193 ;;
194esac
195
196# Sed substitution that helps us do robust quoting. It backslashifies
197# metacharacters that are still active within double-quoted strings.
198sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
199
200# Same as above, but do not quote variable references.
201double_quote_subst='s/\([["`\\]]\)/\\\1/g'
202
203# Sed substitution to delay expansion of an escaped shell variable in a
204# double_quote_subst'ed string.
205delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
206
207# Sed substitution to delay expansion of an escaped single quote.
208delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
209
210# Sed substitution to avoid accidental globbing in evaled expressions
211no_glob_subst='s/\*/\\\*/g'
212
213# Global variables:
214ofile=libtool
215can_build_shared=yes
216
217# All known linkers require a `.a' archive for static linking (except MSVC,
218# which needs '.lib').
219libext=a
220
221with_gnu_ld="$lt_cv_prog_gnu_ld"
222
223old_CC="$CC"
224old_CFLAGS="$CFLAGS"
225
226# Set sane defaults for various variables
227test -z "$CC" && CC=cc
228test -z "$LTCC" && LTCC=$CC
229test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
230test -z "$LD" && LD=ld
231test -z "$ac_objext" && ac_objext=o
232
233_LT_CC_BASENAME([$compiler])
234
235# Only perform the check for file, if the check method requires it
236test -z "$MAGIC_CMD" && MAGIC_CMD=file
237case $deplibs_check_method in
238file_magic*)
239 if test "$file_magic_cmd" = '$MAGIC_CMD'; then
240 _LT_PATH_MAGIC
241 fi
242 ;;
243esac
244
245# Use C for the default configuration in the libtool script
246LT_SUPPORTED_TAG([CC])
247_LT_LANG_C_CONFIG
248_LT_LANG_DEFAULT_CONFIG
249_LT_CONFIG_COMMANDS
250])# _LT_SETUP
251
252
253# _LT_PROG_LTMAIN
254# ---------------
255# Note that this code is called both from `configure', and `config.status'
256# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
257# `config.status' has no value for ac_aux_dir unless we are using Automake,
258# so we pass a copy along to make sure it has a sensible value anyway.
259m4_defun([_LT_PROG_LTMAIN],
260[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
261_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
262ltmain="$ac_aux_dir/ltmain.sh"
263])# _LT_PROG_LTMAIN
264
265
266## ------------------------------------- ##
267## Accumulate code for creating libtool. ##
268## ------------------------------------- ##
269
270# So that we can recreate a full libtool script including additional
271# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
272# in macros and then make a single call at the end using the `libtool'
273# label.
274
275
276# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
277# ----------------------------------------
278# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
279m4_define([_LT_CONFIG_LIBTOOL_INIT],
280[m4_ifval([$1],
281 [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
282 [$1
283])])])
284
285# Initialize.
286m4_define([_LT_OUTPUT_LIBTOOL_INIT])
287
288
289# _LT_CONFIG_LIBTOOL([COMMANDS])
290# ------------------------------
291# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
292m4_define([_LT_CONFIG_LIBTOOL],
293[m4_ifval([$1],
294 [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
295 [$1
296])])])
297
298# Initialize.
299m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
300
301
302# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
303# -----------------------------------------------------
304m4_defun([_LT_CONFIG_SAVE_COMMANDS],
305[_LT_CONFIG_LIBTOOL([$1])
306_LT_CONFIG_LIBTOOL_INIT([$2])
307])
308
309
310# _LT_FORMAT_COMMENT([COMMENT])
311# -----------------------------
312# Add leading comment marks to the start of each line, and a trailing
313# full-stop to the whole comment if one is not present already.
314m4_define([_LT_FORMAT_COMMENT],
315[m4_ifval([$1], [
316m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
317 [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
318)])
319
320
321
322## ------------------------ ##
323## FIXME: Eliminate VARNAME ##
324## ------------------------ ##
325
326
327# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
328# -------------------------------------------------------------------
329# CONFIGNAME is the name given to the value in the libtool script.
330# VARNAME is the (base) name used in the configure script.
331# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
332# VARNAME. Any other value will be used directly.
333m4_define([_LT_DECL],
334[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
335 [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
336 [m4_ifval([$1], [$1], [$2])])
337 lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
338 m4_ifval([$4],
339 [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
340 lt_dict_add_subkey([lt_decl_dict], [$2],
341 [tagged?], [m4_ifval([$5], [yes], [no])])])
342])
343
344
345# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
346# --------------------------------------------------------
347m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
348
349
350# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
351# ------------------------------------------------
352m4_define([lt_decl_tag_varnames],
353[_lt_decl_filter([tagged?], [yes], $@)])
354
355
356# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
357# ---------------------------------------------------------
358m4_define([_lt_decl_filter],
359[m4_case([$#],
360 [0], [m4_fatal([$0: too few arguments: $#])],
361 [1], [m4_fatal([$0: too few arguments: $#: $1])],
362 [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
363 [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
364 [lt_dict_filter([lt_decl_dict], $@)])[]dnl
365])
366
367
368# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
369# --------------------------------------------------
370m4_define([lt_decl_quote_varnames],
371[_lt_decl_filter([value], [1], $@)])
372
373
374# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
375# ---------------------------------------------------
376m4_define([lt_decl_dquote_varnames],
377[_lt_decl_filter([value], [2], $@)])
378
379
380# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
381# ---------------------------------------------------
382m4_define([lt_decl_varnames_tagged],
383[m4_assert([$# <= 2])dnl
384_$0(m4_quote(m4_default([$1], [[, ]])),
385 m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
386 m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
387m4_define([_lt_decl_varnames_tagged],
388[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
389
390
391# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
392# ------------------------------------------------
393m4_define([lt_decl_all_varnames],
394[_$0(m4_quote(m4_default([$1], [[, ]])),
395 m4_if([$2], [],
396 m4_quote(lt_decl_varnames),
397 m4_quote(m4_shift($@))))[]dnl
398])
399m4_define([_lt_decl_all_varnames],
400[lt_join($@, lt_decl_varnames_tagged([$1],
401 lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
402])
403
404
405# _LT_CONFIG_STATUS_DECLARE([VARNAME])
406# ------------------------------------
407# Quote a variable value, and forward it to `config.status' so that its
408# declaration there will have the same value as in `configure'. VARNAME
409# must have a single quote delimited value for this to work.
410m4_define([_LT_CONFIG_STATUS_DECLARE],
411[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
412
413
414# _LT_CONFIG_STATUS_DECLARATIONS
415# ------------------------------
416# We delimit libtool config variables with single quotes, so when
417# we write them to config.status, we have to be sure to quote all
418# embedded single quotes properly. In configure, this macro expands
419# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
420#
421# <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
422m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
423[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
424 [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
425
426
427# _LT_LIBTOOL_TAGS
428# ----------------
429# Output comment and list of tags supported by the script
430m4_defun([_LT_LIBTOOL_TAGS],
431[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
432available_tags="_LT_TAGS"dnl
433])
434
435
436# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
437# -----------------------------------
438# Extract the dictionary values for VARNAME (optionally with TAG) and
439# expand to a commented shell variable setting:
440#
441# # Some comment about what VAR is for.
442# visible_name=$lt_internal_name
443m4_define([_LT_LIBTOOL_DECLARE],
444[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
445 [description])))[]dnl
446m4_pushdef([_libtool_name],
447 m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
448m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
449 [0], [_libtool_name=[$]$1],
450 [1], [_libtool_name=$lt_[]$1],
451 [2], [_libtool_name=$lt_[]$1],
452 [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
453m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
454])
455
456
457# _LT_LIBTOOL_CONFIG_VARS
458# -----------------------
459# Produce commented declarations of non-tagged libtool config variables
460# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
461# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
462# section) are produced by _LT_LIBTOOL_TAG_VARS.
463m4_defun([_LT_LIBTOOL_CONFIG_VARS],
464[m4_foreach([_lt_var],
465 m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
466 [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
467
468
469# _LT_LIBTOOL_TAG_VARS(TAG)
470# -------------------------
471m4_define([_LT_LIBTOOL_TAG_VARS],
472[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
473 [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
474
475
476# _LT_TAGVAR(VARNAME, [TAGNAME])
477# ------------------------------
478m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
479
480
481# _LT_CONFIG_COMMANDS
482# -------------------
483# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
484# variables for single and double quote escaping we saved from calls
485# to _LT_DECL, we can put quote escaped variables declarations
486# into `config.status', and then the shell code to quote escape them in
487# for loops in `config.status'. Finally, any additional code accumulated
488# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
489m4_defun([_LT_CONFIG_COMMANDS],
490[AC_PROVIDE_IFELSE([LT_OUTPUT],
491 dnl If the libtool generation code has been placed in $CONFIG_LT,
492 dnl instead of duplicating it all over again into config.status,
493 dnl then we will have config.status run $CONFIG_LT later, so it
494 dnl needs to know what name is stored there:
495 [AC_CONFIG_COMMANDS([libtool],
496 [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
497 dnl If the libtool generation code is destined for config.status,
498 dnl expand the accumulated commands and init code now:
499 [AC_CONFIG_COMMANDS([libtool],
500 [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
501])#_LT_CONFIG_COMMANDS
502
503
504# Initialize.
505m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
506[
507
508# The HP-UX ksh and POSIX shell print the target directory to stdout
509# if CDPATH is set.
510(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
511
512sed_quote_subst='$sed_quote_subst'
513double_quote_subst='$double_quote_subst'
514delay_variable_subst='$delay_variable_subst'
515_LT_CONFIG_STATUS_DECLARATIONS
516LTCC='$LTCC'
517LTCFLAGS='$LTCFLAGS'
518compiler='$compiler_DEFAULT'
519
520# Quote evaled strings.
521for var in lt_decl_all_varnames([[ \
522]], lt_decl_quote_varnames); do
523 case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
524 *[[\\\\\\\`\\"\\\$]]*)
525 eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
526 ;;
527 *)
528 eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
529 ;;
530 esac
531done
532
533# Double-quote double-evaled strings.
534for var in lt_decl_all_varnames([[ \
535]], lt_decl_dquote_varnames); do
536 case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
537 *[[\\\\\\\`\\"\\\$]]*)
538 eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
539 ;;
540 *)
541 eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
542 ;;
543 esac
544done
545
546# Fix-up fallback echo if it was mangled by the above quoting rules.
547case \$lt_ECHO in
548*'\\\[$]0 --fallback-echo"')dnl "
549 lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
550 ;;
551esac
552
553_LT_OUTPUT_LIBTOOL_INIT
554])
555
556
557# LT_OUTPUT
558# ---------
559# This macro allows early generation of the libtool script (before
560# AC_OUTPUT is called), incase it is used in configure for compilation
561# tests.
562AC_DEFUN([LT_OUTPUT],
563[: ${CONFIG_LT=./config.lt}
564AC_MSG_NOTICE([creating $CONFIG_LT])
565cat >"$CONFIG_LT" <<_LTEOF
566#! $SHELL
567# Generated by $as_me.
568# Run this file to recreate a libtool stub with the current configuration.
569
570lt_cl_silent=false
571SHELL=\${CONFIG_SHELL-$SHELL}
572_LTEOF
573
574cat >>"$CONFIG_LT" <<\_LTEOF
575AS_SHELL_SANITIZE
576_AS_PREPARE
577
578exec AS_MESSAGE_FD>&1
579exec AS_MESSAGE_LOG_FD>>config.log
580{
581 echo
582 AS_BOX([Running $as_me.])
583} >&AS_MESSAGE_LOG_FD
584
585lt_cl_help="\
586\`$as_me' creates a local libtool stub from the current configuration,
587for use in further configure time tests before the real libtool is
588generated.
589
590Usage: $[0] [[OPTIONS]]
591
592 -h, --help print this help, then exit
593 -V, --version print version number, then exit
594 -q, --quiet do not print progress messages
595 -d, --debug don't remove temporary files
596
597Report bugs to <bug-libtool@gnu.org>."
598
599lt_cl_version="\
600m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
601m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
602configured by $[0], generated by m4_PACKAGE_STRING.
603
604Copyright (C) 2008 Free Software Foundation, Inc.
605This config.lt script is free software; the Free Software Foundation
606gives unlimited permision to copy, distribute and modify it."
607
608while test $[#] != 0
609do
610 case $[1] in
611 --version | --v* | -V )
612 echo "$lt_cl_version"; exit 0 ;;
613 --help | --h* | -h )
614 echo "$lt_cl_help"; exit 0 ;;
615 --debug | --d* | -d )
616 debug=: ;;
617 --quiet | --q* | --silent | --s* | -q )
618 lt_cl_silent=: ;;
619
620 -*) AC_MSG_ERROR([unrecognized option: $[1]
621Try \`$[0] --help' for more information.]) ;;
622
623 *) AC_MSG_ERROR([unrecognized argument: $[1]
624Try \`$[0] --help' for more information.]) ;;
625 esac
626 shift
627done
628
629if $lt_cl_silent; then
630 exec AS_MESSAGE_FD>/dev/null
631fi
632_LTEOF
633
634cat >>"$CONFIG_LT" <<_LTEOF
635_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
636_LTEOF
637
638cat >>"$CONFIG_LT" <<\_LTEOF
639AC_MSG_NOTICE([creating $ofile])
640_LT_OUTPUT_LIBTOOL_COMMANDS
641AS_EXIT(0)
642_LTEOF
643chmod +x "$CONFIG_LT"
644
645# configure is writing to config.log, but config.lt does its own redirection,
646# appending to config.log, which fails on DOS, as config.log is still kept
647# open by configure. Here we exec the FD to /dev/null, effectively closing
648# config.log, so it can be properly (re)opened and appended to by config.lt.
649if test "$no_create" != yes; then
650 lt_cl_success=:
651 test "$silent" = yes &&
652 lt_config_lt_args="$lt_config_lt_args --quiet"
653 exec AS_MESSAGE_LOG_FD>/dev/null
654 $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
655 exec AS_MESSAGE_LOG_FD>>config.log
656 $lt_cl_success || AS_EXIT(1)
657fi
658])# LT_OUTPUT
659
660
661# _LT_CONFIG(TAG)
662# ---------------
663# If TAG is the built-in tag, create an initial libtool script with a
664# default configuration from the untagged config vars. Otherwise add code
665# to config.status for appending the configuration named by TAG from the
666# matching tagged config vars.
667m4_defun([_LT_CONFIG],
668[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
669_LT_CONFIG_SAVE_COMMANDS([
670 m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
671 m4_if(_LT_TAG, [C], [
672 # See if we are running on zsh, and set the options which allow our
673 # commands through without removal of \ escapes.
674 if test -n "${ZSH_VERSION+set}" ; then
675 setopt NO_GLOB_SUBST
676 fi
677
678 cfgfile="${ofile}T"
679 trap "$RM \"$cfgfile\"; exit 1" 1 2 15
680 $RM "$cfgfile"
681
682 cat <<_LT_EOF >> "$cfgfile"
683#! $SHELL
684
685# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
686# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
687# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
688# NOTE: Changes made to this file will be lost: look at ltmain.sh.
689#
690_LT_COPYING
691_LT_LIBTOOL_TAGS
692
693# ### BEGIN LIBTOOL CONFIG
694_LT_LIBTOOL_CONFIG_VARS
695_LT_LIBTOOL_TAG_VARS
696# ### END LIBTOOL CONFIG
697
698_LT_EOF
699
700 case $host_os in
701 aix3*)
702 cat <<\_LT_EOF >> "$cfgfile"
703# AIX sometimes has problems with the GCC collect2 program. For some
704# reason, if we set the COLLECT_NAMES environment variable, the problems
705# vanish in a puff of smoke.
706if test "X${COLLECT_NAMES+set}" != Xset; then
707 COLLECT_NAMES=
708 export COLLECT_NAMES
709fi
710_LT_EOF
711 ;;
712 esac
713
714 _LT_PROG_LTMAIN
715
716 # We use sed instead of cat because bash on DJGPP gets confused if
717 # if finds mixed CR/LF and LF-only lines. Since sed operates in
718 # text mode, it properly converts lines to CR/LF. This bash problem
719 # is reportedly fixed, but why not run on old versions too?
720 sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
721 || (rm -f "$cfgfile"; exit 1)
722
723 _LT_PROG_XSI_SHELLFNS
724
725 sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
726 || (rm -f "$cfgfile"; exit 1)
727
728 mv -f "$cfgfile" "$ofile" ||
729 (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
730 chmod +x "$ofile"
731],
732[cat <<_LT_EOF >> "$ofile"
733
734dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
735dnl in a comment (ie after a #).
736# ### BEGIN LIBTOOL TAG CONFIG: $1
737_LT_LIBTOOL_TAG_VARS(_LT_TAG)
738# ### END LIBTOOL TAG CONFIG: $1
739_LT_EOF
740])dnl /m4_if
741],
742[m4_if([$1], [], [
743 PACKAGE='$PACKAGE'
744 VERSION='$VERSION'
745 TIMESTAMP='$TIMESTAMP'
746 RM='$RM'
747 ofile='$ofile'], [])
748])dnl /_LT_CONFIG_SAVE_COMMANDS
749])# _LT_CONFIG
750
751
752# LT_SUPPORTED_TAG(TAG)
753# ---------------------
754# Trace this macro to discover what tags are supported by the libtool
755# --tag option, using:
756# autoconf --trace 'LT_SUPPORTED_TAG:$1'
757AC_DEFUN([LT_SUPPORTED_TAG], [])
758
759
760# C support is built-in for now
761m4_define([_LT_LANG_C_enabled], [])
762m4_define([_LT_TAGS], [])
763
764
765# LT_LANG(LANG)
766# -------------
767# Enable libtool support for the given language if not already enabled.
768AC_DEFUN([LT_LANG],
769[AC_BEFORE([$0], [LT_OUTPUT])dnl
770m4_case([$1],
771 [C], [_LT_LANG(C)],
772 [C++], [_LT_LANG(CXX)],
773 [Java], [_LT_LANG(GCJ)],
774 [Fortran 77], [_LT_LANG(F77)],
775 [Fortran], [_LT_LANG(FC)],
776 [Windows Resource], [_LT_LANG(RC)],
777 [m4_ifdef([_LT_LANG_]$1[_CONFIG],
778 [_LT_LANG($1)],
779 [m4_fatal([$0: unsupported language: "$1"])])])dnl
780])# LT_LANG
781
782
783# _LT_LANG(LANGNAME)
784# ------------------
785m4_defun([_LT_LANG],
786[m4_ifdef([_LT_LANG_]$1[_enabled], [],
787 [LT_SUPPORTED_TAG([$1])dnl
788 m4_append([_LT_TAGS], [$1 ])dnl
789 m4_define([_LT_LANG_]$1[_enabled], [])dnl
790 _LT_LANG_$1_CONFIG($1)])dnl
791])# _LT_LANG
792
793
794# _LT_LANG_DEFAULT_CONFIG
795# -----------------------
796m4_defun([_LT_LANG_DEFAULT_CONFIG],
797[AC_PROVIDE_IFELSE([AC_PROG_CXX],
798 [LT_LANG(CXX)],
799 [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
800
801AC_PROVIDE_IFELSE([AC_PROG_F77],
802 [LT_LANG(F77)],
803 [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
804
805AC_PROVIDE_IFELSE([AC_PROG_FC],
806 [LT_LANG(FC)],
807 [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
808
809dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
810dnl pulling things in needlessly.
811AC_PROVIDE_IFELSE([AC_PROG_GCJ],
812 [LT_LANG(GCJ)],
813 [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
814 [LT_LANG(GCJ)],
815 [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
816 [LT_LANG(GCJ)],
817 [m4_ifdef([AC_PROG_GCJ],
818 [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
819 m4_ifdef([A][M_PROG_GCJ],
820 [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
821 m4_ifdef([LT_PROG_GCJ],
822 [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
823
824AC_PROVIDE_IFELSE([LT_PROG_RC],
825 [LT_LANG(RC)],
826 [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
827])# _LT_LANG_DEFAULT_CONFIG
828
829# Obsolete macros:
830AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
831AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
832AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
833AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
834dnl aclocal-1.4 backwards compatibility:
835dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
836dnl AC_DEFUN([AC_LIBTOOL_F77], [])
837dnl AC_DEFUN([AC_LIBTOOL_FC], [])
838dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
839
840
841# _LT_TAG_COMPILER
842# ----------------
843m4_defun([_LT_TAG_COMPILER],
844[AC_REQUIRE([AC_PROG_CC])dnl
845
846_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
847_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
848_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
849_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
850
851# If no C compiler was specified, use CC.
852LTCC=${LTCC-"$CC"}
853
854# If no C compiler flags were specified, use CFLAGS.
855LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
856
857# Allow CC to be a program name with arguments.
858compiler=$CC
859])# _LT_TAG_COMPILER
860
861
862# _LT_COMPILER_BOILERPLATE
863# ------------------------
864# Check for compiler boilerplate output or warnings with
865# the simple compiler test code.
866m4_defun([_LT_COMPILER_BOILERPLATE],
867[m4_require([_LT_DECL_SED])dnl
868ac_outfile=conftest.$ac_objext
869echo "$lt_simple_compile_test_code" >conftest.$ac_ext
870eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
871_lt_compiler_boilerplate=`cat conftest.err`
872$RM conftest*
873])# _LT_COMPILER_BOILERPLATE
874
875
876# _LT_LINKER_BOILERPLATE
877# ----------------------
878# Check for linker boilerplate output or warnings with
879# the simple link test code.
880m4_defun([_LT_LINKER_BOILERPLATE],
881[m4_require([_LT_DECL_SED])dnl
882ac_outfile=conftest.$ac_objext
883echo "$lt_simple_link_test_code" >conftest.$ac_ext
884eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
885_lt_linker_boilerplate=`cat conftest.err`
886$RM -r conftest*
887])# _LT_LINKER_BOILERPLATE
888
889# _LT_REQUIRED_DARWIN_CHECKS
890# -------------------------
891m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
892 case $host_os in
893 rhapsody* | darwin*)
894 AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
895 AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
896 AC_CHECK_TOOL([LIPO], [lipo], [:])
897 AC_CHECK_TOOL([OTOOL], [otool], [:])
898 AC_CHECK_TOOL([OTOOL64], [otool64], [:])
899 _LT_DECL([], [DSYMUTIL], [1],
900 [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
901 _LT_DECL([], [NMEDIT], [1],
902 [Tool to change global to local symbols on Mac OS X])
903 _LT_DECL([], [LIPO], [1],
904 [Tool to manipulate fat objects and archives on Mac OS X])
905 _LT_DECL([], [OTOOL], [1],
906 [ldd/readelf like tool for Mach-O binaries on Mac OS X])
907 _LT_DECL([], [OTOOL64], [1],
908 [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
909
910 AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
911 [lt_cv_apple_cc_single_mod=no
912 if test -z "${LT_MULTI_MODULE}"; then
913 # By default we will add the -single_module flag. You can override
914 # by either setting the environment variable LT_MULTI_MODULE
915 # non-empty at configure time, or by adding -multi_module to the
916 # link flags.
917 rm -rf libconftest.dylib*
918 echo "int foo(void){return 1;}" > conftest.c
919 echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
920-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
921 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
922 -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
923 _lt_result=$?
924 if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
925 lt_cv_apple_cc_single_mod=yes
926 else
927 cat conftest.err >&AS_MESSAGE_LOG_FD
928 fi
929 rm -rf libconftest.dylib*
930 rm -f conftest.*
931 fi])
932 AC_CACHE_CHECK([for -exported_symbols_list linker flag],
933 [lt_cv_ld_exported_symbols_list],
934 [lt_cv_ld_exported_symbols_list=no
935 save_LDFLAGS=$LDFLAGS
936 echo "_main" > conftest.sym
937 LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
938 AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
939 [lt_cv_ld_exported_symbols_list=yes],
940 [lt_cv_ld_exported_symbols_list=no])
941 LDFLAGS="$save_LDFLAGS"
942 ])
943 case $host_os in
944 rhapsody* | darwin1.[[012]])
945 _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
946 darwin1.*)
947 _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
948 darwin*) # darwin 5.x on
949 # if running on 10.5 or later, the deployment target defaults
950 # to the OS version, if on x86, and 10.4, the deployment
951 # target defaults to 10.4. Don't you love it?
952 case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
953 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
954 _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
955 10.[[012]]*)
956 _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
957 10.*)
958 _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
959 esac
960 ;;
961 esac
962 if test "$lt_cv_apple_cc_single_mod" = "yes"; then
963 _lt_dar_single_mod='$single_module'
964 fi
965 if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
966 _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
967 else
968 _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
969 fi
970 if test "$DSYMUTIL" != ":"; then
971 _lt_dsymutil='~$DSYMUTIL $lib || :'
972 else
973 _lt_dsymutil=
974 fi
975 ;;
976 esac
977])
978
979
980# _LT_DARWIN_LINKER_FEATURES
981# --------------------------
982# Checks for linker and compiler features on darwin
983m4_defun([_LT_DARWIN_LINKER_FEATURES],
984[
985 m4_require([_LT_REQUIRED_DARWIN_CHECKS])
986 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
987 _LT_TAGVAR(hardcode_direct, $1)=no
988 _LT_TAGVAR(hardcode_automatic, $1)=yes
989 _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
990 _LT_TAGVAR(whole_archive_flag_spec, $1)=''
991 _LT_TAGVAR(link_all_deplibs, $1)=yes
992 _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
993 case $cc_basename in
994 ifort*) _lt_dar_can_shared=yes ;;
995 *) _lt_dar_can_shared=$GCC ;;
996 esac
997 if test "$_lt_dar_can_shared" = "yes"; then
998 output_verbose_link_cmd=echo
999 _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
1000 _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
1001 _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
1002 _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
1003 m4_if([$1], [CXX],
1004[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
1005 _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
1006 _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
1007 fi
1008],[])
1009 else
1010 _LT_TAGVAR(ld_shlibs, $1)=no
1011 fi
1012])
1013
1014# _LT_SYS_MODULE_PATH_AIX
1015# -----------------------
1016# Links a minimal program and checks the executable
1017# for the system default hardcoded library path. In most cases,
1018# this is /usr/lib:/lib, but when the MPI compilers are used
1019# the location of the communication and MPI libs are included too.
1020# If we don't find anything, use the default library path according
1021# to the aix ld manual.
1022m4_defun([_LT_SYS_MODULE_PATH_AIX],
1023[m4_require([_LT_DECL_SED])dnl
1024AC_LINK_IFELSE(AC_LANG_PROGRAM,[
1025lt_aix_libpath_sed='
1026 /Import File Strings/,/^$/ {
1027 /^0/ {
1028 s/^0 *\(.*\)$/\1/
1029 p
1030 }
1031 }'
1032aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
1033# Check for a 64-bit object if we didn't find anything.
1034if test -z "$aix_libpath"; then
1035 aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
1036fi],[])
1037if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
1038])# _LT_SYS_MODULE_PATH_AIX
1039
1040
1041# _LT_SHELL_INIT(ARG)
1042# -------------------
1043m4_define([_LT_SHELL_INIT],
1044[ifdef([AC_DIVERSION_NOTICE],
1045 [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
1046 [AC_DIVERT_PUSH(NOTICE)])
1047$1
1048AC_DIVERT_POP
1049])# _LT_SHELL_INIT
1050
1051
1052# _LT_PROG_ECHO_BACKSLASH
1053# -----------------------
1054# Add some code to the start of the generated configure script which
1055# will find an echo command which doesn't interpret backslashes.
1056m4_defun([_LT_PROG_ECHO_BACKSLASH],
1057[_LT_SHELL_INIT([
1058# Check that we are running under the correct shell.
1059SHELL=${CONFIG_SHELL-/bin/sh}
1060
1061case X$lt_ECHO in
1062X*--fallback-echo)
1063 # Remove one level of quotation (which was required for Make).
1064 ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
1065 ;;
1066esac
1067
1068ECHO=${lt_ECHO-echo}
1069if test "X[$]1" = X--no-reexec; then
1070 # Discard the --no-reexec flag, and continue.
1071 shift
1072elif test "X[$]1" = X--fallback-echo; then
1073 # Avoid inline document here, it may be left over
1074 :
1075elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
1076 # Yippee, $ECHO works!
1077 :
1078else
1079 # Restart under the correct shell.
1080 exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
1081fi
1082
1083if test "X[$]1" = X--fallback-echo; then
1084 # used as fallback echo
1085 shift
1086 cat <<_LT_EOF
1087[$]*
1088_LT_EOF
1089 exit 0
1090fi
1091
1092# The HP-UX ksh and POSIX shell print the target directory to stdout
1093# if CDPATH is set.
1094(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
1095
1096if test -z "$lt_ECHO"; then
1097 if test "X${echo_test_string+set}" != Xset; then
1098 # find a string as large as possible, as long as the shell can cope with it
1099 for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
1100 # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
1101 if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
1102 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
1103 then
1104 break
1105 fi
1106 done
1107 fi
1108
1109 if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
1110 echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
1111 test "X$echo_testing_string" = "X$echo_test_string"; then
1112 :
1113 else
1114 # The Solaris, AIX, and Digital Unix default echo programs unquote
1115 # backslashes. This makes it impossible to quote backslashes using
1116 # echo "$something" | sed 's/\\/\\\\/g'
1117 #
1118 # So, first we look for a working echo in the user's PATH.
1119
1120 lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
1121 for dir in $PATH /usr/ucb; do
1122 IFS="$lt_save_ifs"
1123 if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
1124 test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
1125 echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
1126 test "X$echo_testing_string" = "X$echo_test_string"; then
1127 ECHO="$dir/echo"
1128 break
1129 fi
1130 done
1131 IFS="$lt_save_ifs"
1132
1133 if test "X$ECHO" = Xecho; then
1134 # We didn't find a better echo, so look for alternatives.
1135 if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
1136 echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
1137 test "X$echo_testing_string" = "X$echo_test_string"; then
1138 # This shell has a builtin print -r that does the trick.
1139 ECHO='print -r'
1140 elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
1141 test "X$CONFIG_SHELL" != X/bin/ksh; then
1142 # If we have ksh, try running configure again with it.
1143 ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
1144 export ORIGINAL_CONFIG_SHELL
1145 CONFIG_SHELL=/bin/ksh
1146 export CONFIG_SHELL
1147 exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
1148 else
1149 # Try using printf.
1150 ECHO='printf %s\n'
1151 if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
1152 echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
1153 test "X$echo_testing_string" = "X$echo_test_string"; then
1154 # Cool, printf works
1155 :
1156 elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
1157 test "X$echo_testing_string" = 'X\t' &&
1158 echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
1159 test "X$echo_testing_string" = "X$echo_test_string"; then
1160 CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
1161 export CONFIG_SHELL
1162 SHELL="$CONFIG_SHELL"
1163 export SHELL
1164 ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
1165 elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
1166 test "X$echo_testing_string" = 'X\t' &&
1167 echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
1168 test "X$echo_testing_string" = "X$echo_test_string"; then
1169 ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
1170 else
1171 # maybe with a smaller string...
1172 prev=:
1173
1174 for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
1175 if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
1176 then
1177 break
1178 fi
1179 prev="$cmd"
1180 done
1181
1182 if test "$prev" != 'sed 50q "[$]0"'; then
1183 echo_test_string=`eval $prev`
1184 export echo_test_string
1185 exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
1186 else
1187 # Oops. We lost completely, so just stick with echo.
1188 ECHO=echo
1189 fi
1190 fi
1191 fi
1192 fi
1193 fi
1194fi
1195
1196# Copy echo and quote the copy suitably for passing to libtool from
1197# the Makefile, instead of quoting the original, which is used later.
1198lt_ECHO=$ECHO
1199if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
1200 lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
1201fi
1202
1203AC_SUBST(lt_ECHO)
1204])
1205_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
1206_LT_DECL([], [ECHO], [1],
1207 [An echo program that does not interpret backslashes])
1208])# _LT_PROG_ECHO_BACKSLASH
1209
1210
1211# _LT_ENABLE_LOCK
1212# ---------------
1213m4_defun([_LT_ENABLE_LOCK],
1214[AC_ARG_ENABLE([libtool-lock],
1215 [AS_HELP_STRING([--disable-libtool-lock],
1216 [avoid locking (might break parallel builds)])])
1217test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
1218
1219# Some flags need to be propagated to the compiler or linker for good
1220# libtool support.
1221case $host in
1222ia64-*-hpux*)
1223 # Find out which ABI we are using.
1224 echo 'int i;' > conftest.$ac_ext
1225 if AC_TRY_EVAL(ac_compile); then
1226 case `/usr/bin/file conftest.$ac_objext` in
1227 *ELF-32*)
1228 HPUX_IA64_MODE="32"
1229 ;;
1230 *ELF-64*)
1231 HPUX_IA64_MODE="64"
1232 ;;
1233 esac
1234 fi
1235 rm -rf conftest*
1236 ;;
1237*-*-irix6*)
1238 # Find out which ABI we are using.
1239 echo '[#]line __oline__ "configure"' > conftest.$ac_ext
1240 if AC_TRY_EVAL(ac_compile); then
1241 if test "$lt_cv_prog_gnu_ld" = yes; then
1242 case `/usr/bin/file conftest.$ac_objext` in
1243 *32-bit*)
1244 LD="${LD-ld} -melf32bsmip"
1245 ;;
1246 *N32*)
1247 LD="${LD-ld} -melf32bmipn32"
1248 ;;
1249 *64-bit*)
1250 LD="${LD-ld} -melf64bmip"
1251 ;;
1252 esac
1253 else
1254 case `/usr/bin/file conftest.$ac_objext` in
1255 *32-bit*)
1256 LD="${LD-ld} -32"
1257 ;;
1258 *N32*)
1259 LD="${LD-ld} -n32"
1260 ;;
1261 *64-bit*)
1262 LD="${LD-ld} -64"
1263 ;;
1264 esac
1265 fi
1266 fi
1267 rm -rf conftest*
1268 ;;
1269
1270x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
1271s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
1272 # Find out which ABI we are using.
1273 echo 'int i;' > conftest.$ac_ext
1274 if AC_TRY_EVAL(ac_compile); then
1275 case `/usr/bin/file conftest.o` in
1276 *32-bit*)
1277 case $host in
1278 x86_64-*kfreebsd*-gnu)
1279 LD="${LD-ld} -m elf_i386_fbsd"
1280 ;;
1281 x86_64-*linux*)
1282 LD="${LD-ld} -m elf_i386"
1283 ;;
1284 ppc64-*linux*|powerpc64-*linux*)
1285 LD="${LD-ld} -m elf32ppclinux"
1286 ;;
1287 s390x-*linux*)
1288 LD="${LD-ld} -m elf_s390"
1289 ;;
1290 sparc64-*linux*)
1291 LD="${LD-ld} -m elf32_sparc"
1292 ;;
1293 esac
1294 ;;
1295 *64-bit*)
1296 case $host in
1297 x86_64-*kfreebsd*-gnu)
1298 LD="${LD-ld} -m elf_x86_64_fbsd"
1299 ;;
1300 x86_64-*linux*)
1301 LD="${LD-ld} -m elf_x86_64"
1302 ;;
1303 ppc*-*linux*|powerpc*-*linux*)
1304 LD="${LD-ld} -m elf64ppc"
1305 ;;
1306 s390*-*linux*|s390*-*tpf*)
1307 LD="${LD-ld} -m elf64_s390"
1308 ;;
1309 sparc*-*linux*)
1310 LD="${LD-ld} -m elf64_sparc"
1311 ;;
1312 esac
1313 ;;
1314 esac
1315 fi
1316 rm -rf conftest*
1317 ;;
1318
1319*-*-sco3.2v5*)
1320 # On SCO OpenServer 5, we need -belf to get full-featured binaries.
1321 SAVE_CFLAGS="$CFLAGS"
1322 CFLAGS="$CFLAGS -belf"
1323 AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
1324 [AC_LANG_PUSH(C)
1325 AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
1326 AC_LANG_POP])
1327 if test x"$lt_cv_cc_needs_belf" != x"yes"; then
1328 # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
1329 CFLAGS="$SAVE_CFLAGS"
1330 fi
1331 ;;
1332sparc*-*solaris*)
1333 # Find out which ABI we are using.
1334 echo 'int i;' > conftest.$ac_ext
1335 if AC_TRY_EVAL(ac_compile); then
1336 case `/usr/bin/file conftest.o` in
1337 *64-bit*)
1338 case $lt_cv_prog_gnu_ld in
1339 yes*) LD="${LD-ld} -m elf64_sparc" ;;
1340 *)
1341 if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
1342 LD="${LD-ld} -64"
1343 fi
1344 ;;
1345 esac
1346 ;;
1347 esac
1348 fi
1349 rm -rf conftest*
1350 ;;
1351esac
1352
1353need_locks="$enable_libtool_lock"
1354])# _LT_ENABLE_LOCK
1355
1356
1357# _LT_CMD_OLD_ARCHIVE
1358# -------------------
1359m4_defun([_LT_CMD_OLD_ARCHIVE],
1360[AC_CHECK_TOOL(AR, ar, false)
1361test -z "$AR" && AR=ar
1362test -z "$AR_FLAGS" && AR_FLAGS=cru
1363_LT_DECL([], [AR], [1], [The archiver])
1364_LT_DECL([], [AR_FLAGS], [1])
1365
1366AC_CHECK_TOOL(STRIP, strip, :)
1367test -z "$STRIP" && STRIP=:
1368_LT_DECL([], [STRIP], [1], [A symbol stripping program])
1369
1370AC_CHECK_TOOL(RANLIB, ranlib, :)
1371test -z "$RANLIB" && RANLIB=:
1372_LT_DECL([], [RANLIB], [1],
1373 [Commands used to install an old-style archive])
1374
1375# Determine commands to create old-style static archives.
1376old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
1377old_postinstall_cmds='chmod 644 $oldlib'
1378old_postuninstall_cmds=
1379
1380if test -n "$RANLIB"; then
1381 case $host_os in
1382 openbsd*)
1383 old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
1384 ;;
1385 *)
1386 old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
1387 ;;
1388 esac
1389 old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
1390fi
1391_LT_DECL([], [old_postinstall_cmds], [2])
1392_LT_DECL([], [old_postuninstall_cmds], [2])
1393_LT_TAGDECL([], [old_archive_cmds], [2],
1394 [Commands used to build an old-style archive])
1395])# _LT_CMD_OLD_ARCHIVE
1396
1397
1398# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
1399# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
1400# ----------------------------------------------------------------
1401# Check whether the given compiler option works
1402AC_DEFUN([_LT_COMPILER_OPTION],
1403[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
1404m4_require([_LT_DECL_SED])dnl
1405AC_CACHE_CHECK([$1], [$2],
1406 [$2=no
1407 m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
1408 echo "$lt_simple_compile_test_code" > conftest.$ac_ext
1409 lt_compiler_flag="$3"
1410 # Insert the option either (1) after the last *FLAGS variable, or
1411 # (2) before a word containing "conftest.", or (3) at the end.
1412 # Note that $ac_compile itself does not contain backslashes and begins
1413 # with a dollar sign (not a hyphen), so the echo should work correctly.
1414 # The option is referenced via a variable to avoid confusing sed.
1415 lt_compile=`echo "$ac_compile" | $SED \
1416 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1417 -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
1418 -e 's:$: $lt_compiler_flag:'`
1419 (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
1420 (eval "$lt_compile" 2>conftest.err)
1421 ac_status=$?
1422 cat conftest.err >&AS_MESSAGE_LOG_FD
1423 echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
1424 if (exit $ac_status) && test -s "$ac_outfile"; then
1425 # The compiler can only warn and ignore the option if not recognized
1426 # So say no if there are warnings other than the usual output.
1427 $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
1428 $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
1429 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
1430 $2=yes
1431 fi
1432 fi
1433 $RM conftest*
1434])
1435
1436if test x"[$]$2" = xyes; then
1437 m4_if([$5], , :, [$5])
1438else
1439 m4_if([$6], , :, [$6])
1440fi
1441])# _LT_COMPILER_OPTION
1442
1443# Old name:
1444AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
1445dnl aclocal-1.4 backwards compatibility:
1446dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
1447
1448
1449# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
1450# [ACTION-SUCCESS], [ACTION-FAILURE])
1451# ----------------------------------------------------
1452# Check whether the given linker option works
1453AC_DEFUN([_LT_LINKER_OPTION],
1454[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
1455m4_require([_LT_DECL_SED])dnl
1456AC_CACHE_CHECK([$1], [$2],
1457 [$2=no
1458 save_LDFLAGS="$LDFLAGS"
1459 LDFLAGS="$LDFLAGS $3"
1460 echo "$lt_simple_link_test_code" > conftest.$ac_ext
1461 if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
1462 # The linker can only warn and ignore the option if not recognized
1463 # So say no if there are warnings
1464 if test -s conftest.err; then
1465 # Append any errors to the config.log.
1466 cat conftest.err 1>&AS_MESSAGE_LOG_FD
1467 $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
1468 $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
1469 if diff conftest.exp conftest.er2 >/dev/null; then
1470 $2=yes
1471 fi
1472 else
1473 $2=yes
1474 fi
1475 fi
1476 $RM -r conftest*
1477 LDFLAGS="$save_LDFLAGS"
1478])
1479
1480if test x"[$]$2" = xyes; then
1481 m4_if([$4], , :, [$4])
1482else
1483 m4_if([$5], , :, [$5])
1484fi
1485])# _LT_LINKER_OPTION
1486
1487# Old name:
1488AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
1489dnl aclocal-1.4 backwards compatibility:
1490dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
1491
1492
1493# LT_CMD_MAX_LEN
1494#---------------
1495AC_DEFUN([LT_CMD_MAX_LEN],
1496[AC_REQUIRE([AC_CANONICAL_HOST])dnl
1497# find the maximum length of command line arguments
1498AC_MSG_CHECKING([the maximum length of command line arguments])
1499AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
1500 i=0
1501 teststring="ABCD"
1502
1503 case $build_os in
1504 msdosdjgpp*)
1505 # On DJGPP, this test can blow up pretty badly due to problems in libc
1506 # (any single argument exceeding 2000 bytes causes a buffer overrun
1507 # during glob expansion). Even if it were fixed, the result of this
1508 # check would be larger than it should be.
1509 lt_cv_sys_max_cmd_len=12288; # 12K is about right
1510 ;;
1511
1512 gnu*)
1513 # Under GNU Hurd, this test is not required because there is
1514 # no limit to the length of command line arguments.
1515 # Libtool will interpret -1 as no limit whatsoever
1516 lt_cv_sys_max_cmd_len=-1;
1517 ;;
1518
1519 cygwin* | mingw* | cegcc*)
1520 # On Win9x/ME, this test blows up -- it succeeds, but takes
1521 # about 5 minutes as the teststring grows exponentially.
1522 # Worse, since 9x/ME are not pre-emptively multitasking,
1523 # you end up with a "frozen" computer, even though with patience
1524 # the test eventually succeeds (with a max line length of 256k).
1525 # Instead, let's just punt: use the minimum linelength reported by
1526 # all of the supported platforms: 8192 (on NT/2K/XP).
1527 lt_cv_sys_max_cmd_len=8192;
1528 ;;
1529
1530 amigaos*)
1531 # On AmigaOS with pdksh, this test takes hours, literally.
1532 # So we just punt and use a minimum line length of 8192.
1533 lt_cv_sys_max_cmd_len=8192;
1534 ;;
1535
1536 netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
1537 # This has been around since 386BSD, at least. Likely further.
1538 if test -x /sbin/sysctl; then
1539 lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
1540 elif test -x /usr/sbin/sysctl; then
1541 lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
1542 else
1543 lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
1544 fi
1545 # And add a safety zone
1546 lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
1547 lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
1548 ;;
1549
1550 interix*)
1551 # We know the value 262144 and hardcode it with a safety zone (like BSD)
1552 lt_cv_sys_max_cmd_len=196608
1553 ;;
1554
1555 osf*)
1556 # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
1557 # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
1558 # nice to cause kernel panics so lets avoid the loop below.
1559 # First set a reasonable default.
1560 lt_cv_sys_max_cmd_len=16384
1561 #
1562 if test -x /sbin/sysconfig; then
1563 case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
1564 *1*) lt_cv_sys_max_cmd_len=-1 ;;
1565 esac
1566 fi
1567 ;;
1568 sco3.2v5*)
1569 lt_cv_sys_max_cmd_len=102400
1570 ;;
1571 sysv5* | sco5v6* | sysv4.2uw2*)
1572 kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
1573 if test -n "$kargmax"; then
1574 lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
1575 else
1576 lt_cv_sys_max_cmd_len=32768
1577 fi
1578 ;;
1579 *)
1580 lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
1581 if test -n "$lt_cv_sys_max_cmd_len"; then
1582 lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
1583 lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
1584 else
1585 # Make teststring a little bigger before we do anything with it.
1586 # a 1K string should be a reasonable start.
1587 for i in 1 2 3 4 5 6 7 8 ; do
1588 teststring=$teststring$teststring
1589 done
1590 SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
1591 # If test is not a shell built-in, we'll probably end up computing a
1592 # maximum length that is only half of the actual maximum length, but
1593 # we can't tell.
1594 while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
1595 = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
1596 test $i != 17 # 1/2 MB should be enough
1597 do
1598 i=`expr $i + 1`
1599 teststring=$teststring$teststring
1600 done
1601 # Only check the string length outside the loop.
1602 lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
1603 teststring=
1604 # Add a significant safety factor because C++ compilers can tack on
1605 # massive amounts of additional arguments before passing them to the
1606 # linker. It appears as though 1/2 is a usable value.
1607 lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
1608 fi
1609 ;;
1610 esac
1611])
1612if test -n $lt_cv_sys_max_cmd_len ; then
1613 AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
1614else
1615 AC_MSG_RESULT(none)
1616fi
1617max_cmd_len=$lt_cv_sys_max_cmd_len
1618_LT_DECL([], [max_cmd_len], [0],
1619 [What is the maximum length of a command?])
1620])# LT_CMD_MAX_LEN
1621
1622# Old name:
1623AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
1624dnl aclocal-1.4 backwards compatibility:
1625dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
1626
1627
1628# _LT_HEADER_DLFCN
1629# ----------------
1630m4_defun([_LT_HEADER_DLFCN],
1631[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
1632])# _LT_HEADER_DLFCN
1633
1634
1635# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
1636# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
1637# ----------------------------------------------------------------
1638m4_defun([_LT_TRY_DLOPEN_SELF],
1639[m4_require([_LT_HEADER_DLFCN])dnl
1640if test "$cross_compiling" = yes; then :
1641 [$4]
1642else
1643 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
1644 lt_status=$lt_dlunknown
1645 cat > conftest.$ac_ext <<_LT_EOF
1646[#line __oline__ "configure"
1647#include "confdefs.h"
1648
1649#if HAVE_DLFCN_H
1650#include <dlfcn.h>
1651#endif
1652
1653#include <stdio.h>
1654
1655#ifdef RTLD_GLOBAL
1656# define LT_DLGLOBAL RTLD_GLOBAL
1657#else
1658# ifdef DL_GLOBAL
1659# define LT_DLGLOBAL DL_GLOBAL
1660# else
1661# define LT_DLGLOBAL 0
1662# endif
1663#endif
1664
1665/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
1666 find out it does not work in some platform. */
1667#ifndef LT_DLLAZY_OR_NOW
1668# ifdef RTLD_LAZY
1669# define LT_DLLAZY_OR_NOW RTLD_LAZY
1670# else
1671# ifdef DL_LAZY
1672# define LT_DLLAZY_OR_NOW DL_LAZY
1673# else
1674# ifdef RTLD_NOW
1675# define LT_DLLAZY_OR_NOW RTLD_NOW
1676# else
1677# ifdef DL_NOW
1678# define LT_DLLAZY_OR_NOW DL_NOW
1679# else
1680# define LT_DLLAZY_OR_NOW 0
1681# endif
1682# endif
1683# endif
1684# endif
1685#endif
1686
1687void fnord() { int i=42;}
1688int main ()
1689{
1690 void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
1691 int status = $lt_dlunknown;
1692
1693 if (self)
1694 {
1695 if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
1696 else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
1697 /* dlclose (self); */
1698 }
1699 else
1700 puts (dlerror ());
1701
1702 return status;
1703}]
1704_LT_EOF
1705 if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
1706 (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
1707 lt_status=$?
1708 case x$lt_status in
1709 x$lt_dlno_uscore) $1 ;;
1710 x$lt_dlneed_uscore) $2 ;;
1711 x$lt_dlunknown|x*) $3 ;;
1712 esac
1713 else :
1714 # compilation failed
1715 $3
1716 fi
1717fi
1718rm -fr conftest*
1719])# _LT_TRY_DLOPEN_SELF
1720
1721
1722# LT_SYS_DLOPEN_SELF
1723# ------------------
1724AC_DEFUN([LT_SYS_DLOPEN_SELF],
1725[m4_require([_LT_HEADER_DLFCN])dnl
1726if test "x$enable_dlopen" != xyes; then
1727 enable_dlopen=unknown
1728 enable_dlopen_self=unknown
1729 enable_dlopen_self_static=unknown
1730else
1731 lt_cv_dlopen=no
1732 lt_cv_dlopen_libs=
1733
1734 case $host_os in
1735 beos*)
1736 lt_cv_dlopen="load_add_on"
1737 lt_cv_dlopen_libs=
1738 lt_cv_dlopen_self=yes
1739 ;;
1740
1741 mingw* | pw32* | cegcc*)
1742 lt_cv_dlopen="LoadLibrary"
1743 lt_cv_dlopen_libs=
1744 ;;
1745
1746 cygwin*)
1747 lt_cv_dlopen="dlopen"
1748 lt_cv_dlopen_libs=
1749 ;;
1750
1751 darwin*)
1752 # if libdl is installed we need to link against it
1753 AC_CHECK_LIB([dl], [dlopen],
1754 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
1755 lt_cv_dlopen="dyld"
1756 lt_cv_dlopen_libs=
1757 lt_cv_dlopen_self=yes
1758 ])
1759 ;;
1760
1761 *)
1762 AC_CHECK_FUNC([shl_load],
1763 [lt_cv_dlopen="shl_load"],
1764 [AC_CHECK_LIB([dld], [shl_load],
1765 [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
1766 [AC_CHECK_FUNC([dlopen],
1767 [lt_cv_dlopen="dlopen"],
1768 [AC_CHECK_LIB([dl], [dlopen],
1769 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
1770 [AC_CHECK_LIB([svld], [dlopen],
1771 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
1772 [AC_CHECK_LIB([dld], [dld_link],
1773 [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
1774 ])
1775 ])
1776 ])
1777 ])
1778 ])
1779 ;;
1780 esac
1781
1782 if test "x$lt_cv_dlopen" != xno; then
1783 enable_dlopen=yes
1784 else
1785 enable_dlopen=no
1786 fi
1787
1788 case $lt_cv_dlopen in
1789 dlopen)
1790 save_CPPFLAGS="$CPPFLAGS"
1791 test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
1792
1793 save_LDFLAGS="$LDFLAGS"
1794 wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
1795
1796 save_LIBS="$LIBS"
1797 LIBS="$lt_cv_dlopen_libs $LIBS"
1798
1799 AC_CACHE_CHECK([whether a program can dlopen itself],
1800 lt_cv_dlopen_self, [dnl
1801 _LT_TRY_DLOPEN_SELF(
1802 lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
1803 lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
1804 ])
1805
1806 if test "x$lt_cv_dlopen_self" = xyes; then
1807 wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
1808 AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
1809 lt_cv_dlopen_self_static, [dnl
1810 _LT_TRY_DLOPEN_SELF(
1811 lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
1812 lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
1813 ])
1814 fi
1815
1816 CPPFLAGS="$save_CPPFLAGS"
1817 LDFLAGS="$save_LDFLAGS"
1818 LIBS="$save_LIBS"
1819 ;;
1820 esac
1821
1822 case $lt_cv_dlopen_self in
1823 yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
1824 *) enable_dlopen_self=unknown ;;
1825 esac
1826
1827 case $lt_cv_dlopen_self_static in
1828 yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
1829 *) enable_dlopen_self_static=unknown ;;
1830 esac
1831fi
1832_LT_DECL([dlopen_support], [enable_dlopen], [0],
1833 [Whether dlopen is supported])
1834_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
1835 [Whether dlopen of programs is supported])
1836_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
1837 [Whether dlopen of statically linked programs is supported])
1838])# LT_SYS_DLOPEN_SELF
1839
1840# Old name:
1841AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
1842dnl aclocal-1.4 backwards compatibility:
1843dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
1844
1845
1846# _LT_COMPILER_C_O([TAGNAME])
1847# ---------------------------
1848# Check to see if options -c and -o are simultaneously supported by compiler.
1849# This macro does not hard code the compiler like AC_PROG_CC_C_O.
1850m4_defun([_LT_COMPILER_C_O],
1851[m4_require([_LT_DECL_SED])dnl
1852m4_require([_LT_FILEUTILS_DEFAULTS])dnl
1853m4_require([_LT_TAG_COMPILER])dnl
1854AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
1855 [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
1856 [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
1857 $RM -r conftest 2>/dev/null
1858 mkdir conftest
1859 cd conftest
1860 mkdir out
1861 echo "$lt_simple_compile_test_code" > conftest.$ac_ext
1862
1863 lt_compiler_flag="-o out/conftest2.$ac_objext"
1864 # Insert the option either (1) after the last *FLAGS variable, or
1865 # (2) before a word containing "conftest.", or (3) at the end.
1866 # Note that $ac_compile itself does not contain backslashes and begins
1867 # with a dollar sign (not a hyphen), so the echo should work correctly.
1868 lt_compile=`echo "$ac_compile" | $SED \
1869 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1870 -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
1871 -e 's:$: $lt_compiler_flag:'`
1872 (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
1873 (eval "$lt_compile" 2>out/conftest.err)
1874 ac_status=$?
1875 cat out/conftest.err >&AS_MESSAGE_LOG_FD
1876 echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
1877 if (exit $ac_status) && test -s out/conftest2.$ac_objext
1878 then
1879 # The compiler can only warn and ignore the option if not recognized
1880 # So say no if there are warnings
1881 $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
1882 $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
1883 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
1884 _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
1885 fi
1886 fi
1887 chmod u+w . 2>&AS_MESSAGE_LOG_FD
1888 $RM conftest*
1889 # SGI C++ compiler will create directory out/ii_files/ for
1890 # template instantiation
1891 test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
1892 $RM out/* && rmdir out
1893 cd ..
1894 $RM -r conftest
1895 $RM conftest*
1896])
1897_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
1898 [Does compiler simultaneously support -c and -o options?])
1899])# _LT_COMPILER_C_O
1900
1901
1902# _LT_COMPILER_FILE_LOCKS([TAGNAME])
1903# ----------------------------------
1904# Check to see if we can do hard links to lock some files if needed
1905m4_defun([_LT_COMPILER_FILE_LOCKS],
1906[m4_require([_LT_ENABLE_LOCK])dnl
1907m4_require([_LT_FILEUTILS_DEFAULTS])dnl
1908_LT_COMPILER_C_O([$1])
1909
1910hard_links="nottested"
1911if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
1912 # do not overwrite the value of need_locks provided by the user
1913 AC_MSG_CHECKING([if we can lock with hard links])
1914 hard_links=yes
1915 $RM conftest*
1916 ln conftest.a conftest.b 2>/dev/null && hard_links=no
1917 touch conftest.a
1918 ln conftest.a conftest.b 2>&5 || hard_links=no
1919 ln conftest.a conftest.b 2>/dev/null && hard_links=no
1920 AC_MSG_RESULT([$hard_links])
1921 if test "$hard_links" = no; then
1922 AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
1923 need_locks=warn
1924 fi
1925else
1926 need_locks=no
1927fi
1928_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
1929])# _LT_COMPILER_FILE_LOCKS
1930
1931
1932# _LT_CHECK_OBJDIR
1933# ----------------
1934m4_defun([_LT_CHECK_OBJDIR],
1935[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
1936[rm -f .libs 2>/dev/null
1937mkdir .libs 2>/dev/null
1938if test -d .libs; then
1939 lt_cv_objdir=.libs
1940else
1941 # MS-DOS does not allow filenames that begin with a dot.
1942 lt_cv_objdir=_libs
1943fi
1944rmdir .libs 2>/dev/null])
1945objdir=$lt_cv_objdir
1946_LT_DECL([], [objdir], [0],
1947 [The name of the directory that contains temporary libtool files])dnl
1948m4_pattern_allow([LT_OBJDIR])dnl
1949AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
1950 [Define to the sub-directory in which libtool stores uninstalled libraries.])
1951])# _LT_CHECK_OBJDIR
1952
1953
1954# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
1955# --------------------------------------
1956# Check hardcoding attributes.
1957m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
1958[AC_MSG_CHECKING([how to hardcode library paths into programs])
1959_LT_TAGVAR(hardcode_action, $1)=
1960if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
1961 test -n "$_LT_TAGVAR(runpath_var, $1)" ||
1962 test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
1963
1964 # We can hardcode non-existent directories.
1965 if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
1966 # If the only mechanism to avoid hardcoding is shlibpath_var, we
1967 # have to relink, otherwise we might link with an installed library
1968 # when we should be linking with a yet-to-be-installed one
1969 ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
1970 test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
1971 # Linking always hardcodes the temporary library directory.
1972 _LT_TAGVAR(hardcode_action, $1)=relink
1973 else
1974 # We can link without hardcoding, and we can hardcode nonexisting dirs.
1975 _LT_TAGVAR(hardcode_action, $1)=immediate
1976 fi
1977else
1978 # We cannot hardcode anything, or else we can only hardcode existing
1979 # directories.
1980 _LT_TAGVAR(hardcode_action, $1)=unsupported
1981fi
1982AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
1983
1984if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
1985 test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
1986 # Fast installation is not supported
1987 enable_fast_install=no
1988elif test "$shlibpath_overrides_runpath" = yes ||
1989 test "$enable_shared" = no; then
1990 # Fast installation is not necessary
1991 enable_fast_install=needless
1992fi
1993_LT_TAGDECL([], [hardcode_action], [0],
1994 [How to hardcode a shared library path into an executable])
1995])# _LT_LINKER_HARDCODE_LIBPATH
1996
1997
1998# _LT_CMD_STRIPLIB
1999# ----------------
2000m4_defun([_LT_CMD_STRIPLIB],
2001[m4_require([_LT_DECL_EGREP])
2002striplib=
2003old_striplib=
2004AC_MSG_CHECKING([whether stripping libraries is possible])
2005if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
2006 test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
2007 test -z "$striplib" && striplib="$STRIP --strip-unneeded"
2008 AC_MSG_RESULT([yes])
2009else
2010# FIXME - insert some real tests, host_os isn't really good enough
2011 case $host_os in
2012 darwin*)
2013 if test -n "$STRIP" ; then
2014 striplib="$STRIP -x"
2015 old_striplib="$STRIP -S"
2016 AC_MSG_RESULT([yes])
2017 else
2018 AC_MSG_RESULT([no])
2019 fi
2020 ;;
2021 *)
2022 AC_MSG_RESULT([no])
2023 ;;
2024 esac
2025fi
2026_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
2027_LT_DECL([], [striplib], [1])
2028])# _LT_CMD_STRIPLIB
2029
2030
2031# _LT_SYS_DYNAMIC_LINKER([TAG])
2032# -----------------------------
2033# PORTME Fill in your ld.so characteristics
2034m4_defun([_LT_SYS_DYNAMIC_LINKER],
2035[AC_REQUIRE([AC_CANONICAL_HOST])dnl
2036m4_require([_LT_DECL_EGREP])dnl
2037m4_require([_LT_FILEUTILS_DEFAULTS])dnl
2038m4_require([_LT_DECL_OBJDUMP])dnl
2039m4_require([_LT_DECL_SED])dnl
2040AC_MSG_CHECKING([dynamic linker characteristics])
2041m4_if([$1],
2042 [], [
2043if test "$GCC" = yes; then
2044 case $host_os in
2045 darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
2046 *) lt_awk_arg="/^libraries:/" ;;
2047 esac
2048 lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
2049 if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
2050 # if the path contains ";" then we assume it to be the separator
2051 # otherwise default to the standard path separator (i.e. ":") - it is
2052 # assumed that no part of a normal pathname contains ";" but that should
2053 # okay in the real world where ";" in dirpaths is itself problematic.
2054 lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
2055 else
2056 lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
2057 fi
2058 # Ok, now we have the path, separated by spaces, we can step through it
2059 # and add multilib dir if necessary.
2060 lt_tmp_lt_search_path_spec=
2061 lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
2062 for lt_sys_path in $lt_search_path_spec; do
2063 if test -d "$lt_sys_path/$lt_multi_os_dir"; then
2064 lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
2065 else
2066 test -d "$lt_sys_path" && \
2067 lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
2068 fi
2069 done
2070 lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
2071BEGIN {RS=" "; FS="/|\n";} {
2072 lt_foo="";
2073 lt_count=0;
2074 for (lt_i = NF; lt_i > 0; lt_i--) {
2075 if ($lt_i != "" && $lt_i != ".") {
2076 if ($lt_i == "..") {
2077 lt_count++;
2078 } else {
2079 if (lt_count == 0) {
2080 lt_foo="/" $lt_i lt_foo;
2081 } else {
2082 lt_count--;
2083 }
2084 }
2085 }
2086 }
2087 if (lt_foo != "") { lt_freq[[lt_foo]]++; }
2088 if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
2089}'`
2090 sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
2091else
2092 sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
2093fi])
2094library_names_spec=
2095libname_spec='lib$name'
2096soname_spec=
2097shrext_cmds=".so"
2098postinstall_cmds=
2099postuninstall_cmds=
2100finish_cmds=
2101finish_eval=
2102shlibpath_var=
2103shlibpath_overrides_runpath=unknown
2104version_type=none
2105dynamic_linker="$host_os ld.so"
2106sys_lib_dlsearch_path_spec="/lib /usr/lib"
2107need_lib_prefix=unknown
2108hardcode_into_libs=no
2109
2110# when you set need_version to no, make sure it does not cause -set_version
2111# flags to be left without arguments
2112need_version=unknown
2113
2114case $host_os in
2115aix3*)
2116 version_type=linux
2117 library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
2118 shlibpath_var=LIBPATH
2119
2120 # AIX 3 has no versioning support, so we append a major version to the name.
2121 soname_spec='${libname}${release}${shared_ext}$major'
2122 ;;
2123
2124aix[[4-9]]*)
2125 version_type=linux
2126 need_lib_prefix=no
2127 need_version=no
2128 hardcode_into_libs=yes
2129 if test "$host_cpu" = ia64; then
2130 # AIX 5 supports IA64
2131 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
2132 shlibpath_var=LD_LIBRARY_PATH
2133 else
2134 # With GCC up to 2.95.x, collect2 would create an import file
2135 # for dependence libraries. The import file would start with
2136 # the line `#! .'. This would cause the generated library to
2137 # depend on `.', always an invalid library. This was fixed in
2138 # development snapshots of GCC prior to 3.0.
2139 case $host_os in
2140 aix4 | aix4.[[01]] | aix4.[[01]].*)
2141 if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
2142 echo ' yes '
2143 echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
2144 :
2145 else
2146 can_build_shared=no
2147 fi
2148 ;;
2149 esac
2150 # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
2151 # soname into executable. Probably we can add versioning support to
2152 # collect2, so additional links can be useful in future.
2153 if test "$aix_use_runtimelinking" = yes; then
2154 # If using run time linking (on AIX 4.2 or later) use lib<name>.so
2155 # instead of lib<name>.a to let people know that these are not
2156 # typical AIX shared libraries.
2157 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2158 else
2159 # We preserve .a as extension for shared libraries through AIX4.2
2160 # and later when we are not doing run time linking.
2161 library_names_spec='${libname}${release}.a $libname.a'
2162 soname_spec='${libname}${release}${shared_ext}$major'
2163 fi
2164 shlibpath_var=LIBPATH
2165 fi
2166 ;;
2167
2168amigaos*)
2169 case $host_cpu in
2170 powerpc)
2171 # Since July 2007 AmigaOS4 officially supports .so libraries.
2172 # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
2173 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2174 ;;
2175 m68k)
2176 library_names_spec='$libname.ixlibrary $libname.a'
2177 # Create ${libname}_ixlibrary.a entries in /sys/libs.
2178 finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
2179 ;;
2180 esac
2181 ;;
2182
2183beos*)
2184 library_names_spec='${libname}${shared_ext}'
2185 dynamic_linker="$host_os ld.so"
2186 shlibpath_var=LIBRARY_PATH
2187 ;;
2188
2189bsdi[[45]]*)
2190 version_type=linux
2191 need_version=no
2192 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2193 soname_spec='${libname}${release}${shared_ext}$major'
2194 finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
2195 shlibpath_var=LD_LIBRARY_PATH
2196 sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
2197 sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
2198 # the default ld.so.conf also contains /usr/contrib/lib and
2199 # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
2200 # libtool to hard-code these into programs
2201 ;;
2202
2203cygwin* | mingw* | pw32* | cegcc*)
2204 version_type=windows
2205 shrext_cmds=".dll"
2206 need_version=no
2207 need_lib_prefix=no
2208
2209 case $GCC,$host_os in
2210 yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
2211 library_names_spec='$libname.dll.a'
2212 # DLL is installed to $(libdir)/../bin by postinstall_cmds
2213 postinstall_cmds='base_file=`basename \${file}`~
2214 dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
2215 dldir=$destdir/`dirname \$dlpath`~
2216 test -d \$dldir || mkdir -p \$dldir~
2217 $install_prog $dir/$dlname \$dldir/$dlname~
2218 chmod a+x \$dldir/$dlname~
2219 if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
2220 eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
2221 fi'
2222 postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
2223 dlpath=$dir/\$dldll~
2224 $RM \$dlpath'
2225 shlibpath_overrides_runpath=yes
2226
2227 case $host_os in
2228 cygwin*)
2229 # Cygwin DLLs use 'cyg' prefix rather than 'lib'
2230 soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
2231 sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
2232 ;;
2233 mingw* | cegcc*)
2234 # MinGW DLLs use traditional 'lib' prefix
2235 soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
2236 sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
2237 if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
2238 # It is most probably a Windows format PATH printed by
2239 # mingw gcc, but we are running on Cygwin. Gcc prints its search
2240 # path with ; separators, and with drive letters. We can handle the
2241 # drive letters (cygwin fileutils understands them), so leave them,
2242 # especially as we might pass files found there to a mingw objdump,
2243 # which wouldn't understand a cygwinified path. Ahh.
2244 sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
2245 else
2246 sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
2247 fi
2248 ;;
2249 pw32*)
2250 # pw32 DLLs use 'pw' prefix rather than 'lib'
2251 library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
2252 ;;
2253 esac
2254 ;;
2255
2256 *)
2257 library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
2258 ;;
2259 esac
2260 dynamic_linker='Win32 ld.exe'
2261 # FIXME: first we should search . and the directory the executable is in
2262 shlibpath_var=PATH
2263 ;;
2264
2265darwin* | rhapsody*)
2266 dynamic_linker="$host_os dyld"
2267 version_type=darwin
2268 need_lib_prefix=no
2269 need_version=no
2270 library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
2271 soname_spec='${libname}${release}${major}$shared_ext'
2272 shlibpath_overrides_runpath=yes
2273 shlibpath_var=DYLD_LIBRARY_PATH
2274 shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
2275m4_if([$1], [],[
2276 sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
2277 sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
2278 ;;
2279
2280dgux*)
2281 version_type=linux
2282 need_lib_prefix=no
2283 need_version=no
2284 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
2285 soname_spec='${libname}${release}${shared_ext}$major'
2286 shlibpath_var=LD_LIBRARY_PATH
2287 ;;
2288
2289freebsd1*)
2290 dynamic_linker=no
2291 ;;
2292
2293freebsd* | dragonfly*)
2294 # DragonFly does not have aout. When/if they implement a new
2295 # versioning mechanism, adjust this.
2296 if test -x /usr/bin/objformat; then
2297 objformat=`/usr/bin/objformat`
2298 else
2299 case $host_os in
2300 freebsd[[123]]*) objformat=aout ;;
2301 *) objformat=elf ;;
2302 esac
2303 fi
2304 version_type=freebsd-$objformat
2305 case $version_type in
2306 freebsd-elf*)
2307 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
2308 need_version=no
2309 need_lib_prefix=no
2310 ;;
2311 freebsd-*)
2312 library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
2313 need_version=yes
2314 ;;
2315 esac
2316 shlibpath_var=LD_LIBRARY_PATH
2317 case $host_os in
2318 freebsd2*)
2319 shlibpath_overrides_runpath=yes
2320 ;;
2321 freebsd3.[[01]]* | freebsdelf3.[[01]]*)
2322 shlibpath_overrides_runpath=yes
2323 hardcode_into_libs=yes
2324 ;;
2325 freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
2326 freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
2327 shlibpath_overrides_runpath=no
2328 hardcode_into_libs=yes
2329 ;;
2330 *) # from 4.6 on, and DragonFly
2331 shlibpath_overrides_runpath=yes
2332 hardcode_into_libs=yes
2333 ;;
2334 esac
2335 ;;
2336
2337gnu*)
2338 version_type=linux
2339 need_lib_prefix=no
2340 need_version=no
2341 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
2342 soname_spec='${libname}${release}${shared_ext}$major'
2343 shlibpath_var=LD_LIBRARY_PATH
2344 hardcode_into_libs=yes
2345 ;;
2346
2347hpux9* | hpux10* | hpux11*)
2348 # Give a soname corresponding to the major version so that dld.sl refuses to
2349 # link against other versions.
2350 version_type=sunos
2351 need_lib_prefix=no
2352 need_version=no
2353 case $host_cpu in
2354 ia64*)
2355 shrext_cmds='.so'
2356 hardcode_into_libs=yes
2357 dynamic_linker="$host_os dld.so"
2358 shlibpath_var=LD_LIBRARY_PATH
2359 shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
2360 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2361 soname_spec='${libname}${release}${shared_ext}$major'
2362 if test "X$HPUX_IA64_MODE" = X32; then
2363 sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
2364 else
2365 sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
2366 fi
2367 sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
2368 ;;
2369 hppa*64*)
2370 shrext_cmds='.sl'
2371 hardcode_into_libs=yes
2372 dynamic_linker="$host_os dld.sl"
2373 shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
2374 shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
2375 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2376 soname_spec='${libname}${release}${shared_ext}$major'
2377 sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
2378 sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
2379 ;;
2380 *)
2381 shrext_cmds='.sl'
2382 dynamic_linker="$host_os dld.sl"
2383 shlibpath_var=SHLIB_PATH
2384 shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
2385 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2386 soname_spec='${libname}${release}${shared_ext}$major'
2387 ;;
2388 esac
2389 # HP-UX runs *really* slowly unless shared libraries are mode 555.
2390 postinstall_cmds='chmod 555 $lib'
2391 ;;
2392
2393interix[[3-9]]*)
2394 version_type=linux
2395 need_lib_prefix=no
2396 need_version=no
2397 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
2398 soname_spec='${libname}${release}${shared_ext}$major'
2399 dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
2400 shlibpath_var=LD_LIBRARY_PATH
2401 shlibpath_overrides_runpath=no
2402 hardcode_into_libs=yes
2403 ;;
2404
2405irix5* | irix6* | nonstopux*)
2406 case $host_os in
2407 nonstopux*) version_type=nonstopux ;;
2408 *)
2409 if test "$lt_cv_prog_gnu_ld" = yes; then
2410 version_type=linux
2411 else
2412 version_type=irix
2413 fi ;;
2414 esac
2415 need_lib_prefix=no
2416 need_version=no
2417 soname_spec='${libname}${release}${shared_ext}$major'
2418 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
2419 case $host_os in
2420 irix5* | nonstopux*)
2421 libsuff= shlibsuff=
2422 ;;
2423 *)
2424 case $LD in # libtool.m4 will add one of these switches to LD
2425 *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
2426 libsuff= shlibsuff= libmagic=32-bit;;
2427 *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
2428 libsuff=32 shlibsuff=N32 libmagic=N32;;
2429 *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
2430 libsuff=64 shlibsuff=64 libmagic=64-bit;;
2431 *) libsuff= shlibsuff= libmagic=never-match;;
2432 esac
2433 ;;
2434 esac
2435 shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
2436 shlibpath_overrides_runpath=no
2437 sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
2438 sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
2439 hardcode_into_libs=yes
2440 ;;
2441
2442# No shared lib support for Linux oldld, aout, or coff.
2443linux*oldld* | linux*aout* | linux*coff*)
2444 dynamic_linker=no
2445 ;;
2446
2447# This must be Linux ELF.
2448linux* | k*bsd*-gnu | kopensolaris*-gnu)
2449 version_type=linux
2450 need_lib_prefix=no
2451 need_version=no
2452 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2453 soname_spec='${libname}${release}${shared_ext}$major'
2454 finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
2455 shlibpath_var=LD_LIBRARY_PATH
2456 shlibpath_overrides_runpath=no
2457 # Some binutils ld are patched to set DT_RUNPATH
2458 save_LDFLAGS=$LDFLAGS
2459 save_libdir=$libdir
2460 eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
2461 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
2462 AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
2463 [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
2464 [shlibpath_overrides_runpath=yes])])
2465 LDFLAGS=$save_LDFLAGS
2466 libdir=$save_libdir
2467
2468 # This implies no fast_install, which is unacceptable.
2469 # Some rework will be needed to allow for fast_install
2470 # before this can be enabled.
2471 hardcode_into_libs=yes
2472
2473 # Append ld.so.conf contents to the search path
2474 if test -f /etc/ld.so.conf; then
2475 lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
2476 sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
2477 fi
2478
2479 # We used to test for /lib/ld.so.1 and disable shared libraries on
2480 # powerpc, because MkLinux only supported shared libraries with the
2481 # GNU dynamic linker. Since this was broken with cross compilers,
2482 # most powerpc-linux boxes support dynamic linking these days and
2483 # people can always --disable-shared, the test was removed, and we
2484 # assume the GNU/Linux dynamic linker is in use.
2485 dynamic_linker='GNU/Linux ld.so'
2486 ;;
2487
2488netbsdelf*-gnu)
2489 version_type=linux
2490 need_lib_prefix=no
2491 need_version=no
2492 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
2493 soname_spec='${libname}${release}${shared_ext}$major'
2494 shlibpath_var=LD_LIBRARY_PATH
2495 shlibpath_overrides_runpath=no
2496 hardcode_into_libs=yes
2497 dynamic_linker='NetBSD ld.elf_so'
2498 ;;
2499
2500netbsd*)
2501 version_type=sunos
2502 need_lib_prefix=no
2503 need_version=no
2504 if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
2505 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
2506 finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
2507 dynamic_linker='NetBSD (a.out) ld.so'
2508 else
2509 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
2510 soname_spec='${libname}${release}${shared_ext}$major'
2511 dynamic_linker='NetBSD ld.elf_so'
2512 fi
2513 shlibpath_var=LD_LIBRARY_PATH
2514 shlibpath_overrides_runpath=yes
2515 hardcode_into_libs=yes
2516 ;;
2517
2518newsos6)
2519 version_type=linux
2520 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2521 shlibpath_var=LD_LIBRARY_PATH
2522 shlibpath_overrides_runpath=yes
2523 ;;
2524
2525*nto* | *qnx*)
2526 version_type=qnx
2527 need_lib_prefix=no
2528 need_version=no
2529 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2530 soname_spec='${libname}${release}${shared_ext}$major'
2531 shlibpath_var=LD_LIBRARY_PATH
2532 shlibpath_overrides_runpath=no
2533 hardcode_into_libs=yes
2534 dynamic_linker='ldqnx.so'
2535 ;;
2536
2537openbsd*)
2538 version_type=sunos
2539 sys_lib_dlsearch_path_spec="/usr/lib"
2540 need_lib_prefix=no
2541 # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
2542 case $host_os in
2543 openbsd3.3 | openbsd3.3.*) need_version=yes ;;
2544 *) need_version=no ;;
2545 esac
2546 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
2547 finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
2548 shlibpath_var=LD_LIBRARY_PATH
2549 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
2550 case $host_os in
2551 openbsd2.[[89]] | openbsd2.[[89]].*)
2552 shlibpath_overrides_runpath=no
2553 ;;
2554 *)
2555 shlibpath_overrides_runpath=yes
2556 ;;
2557 esac
2558 else
2559 shlibpath_overrides_runpath=yes
2560 fi
2561 ;;
2562
2563os2*)
2564 libname_spec='$name'
2565 shrext_cmds=".dll"
2566 need_lib_prefix=no
2567 library_names_spec='$libname${shared_ext} $libname.a'
2568 dynamic_linker='OS/2 ld.exe'
2569 shlibpath_var=LIBPATH
2570 ;;
2571
2572osf3* | osf4* | osf5*)
2573 version_type=osf
2574 need_lib_prefix=no
2575 need_version=no
2576 soname_spec='${libname}${release}${shared_ext}$major'
2577 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2578 shlibpath_var=LD_LIBRARY_PATH
2579 sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
2580 sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
2581 ;;
2582
2583rdos*)
2584 dynamic_linker=no
2585 ;;
2586
2587solaris*)
2588 version_type=linux
2589 need_lib_prefix=no
2590 need_version=no
2591 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2592 soname_spec='${libname}${release}${shared_ext}$major'
2593 shlibpath_var=LD_LIBRARY_PATH
2594 shlibpath_overrides_runpath=yes
2595 hardcode_into_libs=yes
2596 # ldd complains unless libraries are executable
2597 postinstall_cmds='chmod +x $lib'
2598 ;;
2599
2600sunos4*)
2601 version_type=sunos
2602 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
2603 finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
2604 shlibpath_var=LD_LIBRARY_PATH
2605 shlibpath_overrides_runpath=yes
2606 if test "$with_gnu_ld" = yes; then
2607 need_lib_prefix=no
2608 fi
2609 need_version=yes
2610 ;;
2611
2612sysv4 | sysv4.3*)
2613 version_type=linux
2614 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2615 soname_spec='${libname}${release}${shared_ext}$major'
2616 shlibpath_var=LD_LIBRARY_PATH
2617 case $host_vendor in
2618 sni)
2619 shlibpath_overrides_runpath=no
2620 need_lib_prefix=no
2621 runpath_var=LD_RUN_PATH
2622 ;;
2623 siemens)
2624 need_lib_prefix=no
2625 ;;
2626 motorola)
2627 need_lib_prefix=no
2628 need_version=no
2629 shlibpath_overrides_runpath=no
2630 sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
2631 ;;
2632 esac
2633 ;;
2634
2635sysv4*MP*)
2636 if test -d /usr/nec ;then
2637 version_type=linux
2638 library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
2639 soname_spec='$libname${shared_ext}.$major'
2640 shlibpath_var=LD_LIBRARY_PATH
2641 fi
2642 ;;
2643
2644sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
2645 version_type=freebsd-elf
2646 need_lib_prefix=no
2647 need_version=no
2648 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
2649 soname_spec='${libname}${release}${shared_ext}$major'
2650 shlibpath_var=LD_LIBRARY_PATH
2651 shlibpath_overrides_runpath=yes
2652 hardcode_into_libs=yes
2653 if test "$with_gnu_ld" = yes; then
2654 sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
2655 else
2656 sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
2657 case $host_os in
2658 sco3.2v5*)
2659 sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
2660 ;;
2661 esac
2662 fi
2663 sys_lib_dlsearch_path_spec='/usr/lib'
2664 ;;
2665
2666tpf*)
2667 # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
2668 version_type=linux
2669 need_lib_prefix=no
2670 need_version=no
2671 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2672 shlibpath_var=LD_LIBRARY_PATH
2673 shlibpath_overrides_runpath=no
2674 hardcode_into_libs=yes
2675 ;;
2676
2677uts4*)
2678 version_type=linux
2679 library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
2680 soname_spec='${libname}${release}${shared_ext}$major'
2681 shlibpath_var=LD_LIBRARY_PATH
2682 ;;
2683
2684*)
2685 dynamic_linker=no
2686 ;;
2687esac
2688AC_MSG_RESULT([$dynamic_linker])
2689test "$dynamic_linker" = no && can_build_shared=no
2690
2691variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
2692if test "$GCC" = yes; then
2693 variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
2694fi
2695
2696if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
2697 sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
2698fi
2699if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
2700 sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
2701fi
2702
2703_LT_DECL([], [variables_saved_for_relink], [1],
2704 [Variables whose values should be saved in libtool wrapper scripts and
2705 restored at link time])
2706_LT_DECL([], [need_lib_prefix], [0],
2707 [Do we need the "lib" prefix for modules?])
2708_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
2709_LT_DECL([], [version_type], [0], [Library versioning type])
2710_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
2711_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
2712_LT_DECL([], [shlibpath_overrides_runpath], [0],
2713 [Is shlibpath searched before the hard-coded library search path?])
2714_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
2715_LT_DECL([], [library_names_spec], [1],
2716 [[List of archive names. First name is the real one, the rest are links.
2717 The last name is the one that the linker finds with -lNAME]])
2718_LT_DECL([], [soname_spec], [1],
2719 [[The coded name of the library, if different from the real name]])
2720_LT_DECL([], [postinstall_cmds], [2],
2721 [Command to use after installation of a shared archive])
2722_LT_DECL([], [postuninstall_cmds], [2],
2723 [Command to use after uninstallation of a shared archive])
2724_LT_DECL([], [finish_cmds], [2],
2725 [Commands used to finish a libtool library installation in a directory])
2726_LT_DECL([], [finish_eval], [1],
2727 [[As "finish_cmds", except a single script fragment to be evaled but
2728 not shown]])
2729_LT_DECL([], [hardcode_into_libs], [0],
2730 [Whether we should hardcode library paths into libraries])
2731_LT_DECL([], [sys_lib_search_path_spec], [2],
2732 [Compile-time system search path for libraries])
2733_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
2734 [Run-time system search path for libraries])
2735])# _LT_SYS_DYNAMIC_LINKER
2736
2737
2738# _LT_PATH_TOOL_PREFIX(TOOL)
2739# --------------------------
2740# find a file program which can recognize shared library
2741AC_DEFUN([_LT_PATH_TOOL_PREFIX],
2742[m4_require([_LT_DECL_EGREP])dnl
2743AC_MSG_CHECKING([for $1])
2744AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
2745[case $MAGIC_CMD in
2746[[\\/*] | ?:[\\/]*])
2747 lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
2748 ;;
2749*)
2750 lt_save_MAGIC_CMD="$MAGIC_CMD"
2751 lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
2752dnl $ac_dummy forces splitting on constant user-supplied paths.
2753dnl POSIX.2 word splitting is done only on the output of word expansions,
2754dnl not every word. This closes a longstanding sh security hole.
2755 ac_dummy="m4_if([$2], , $PATH, [$2])"
2756 for ac_dir in $ac_dummy; do
2757 IFS="$lt_save_ifs"
2758 test -z "$ac_dir" && ac_dir=.
2759 if test -f $ac_dir/$1; then
2760 lt_cv_path_MAGIC_CMD="$ac_dir/$1"
2761 if test -n "$file_magic_test_file"; then
2762 case $deplibs_check_method in
2763 "file_magic "*)
2764 file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
2765 MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
2766 if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
2767 $EGREP "$file_magic_regex" > /dev/null; then
2768 :
2769 else
2770 cat <<_LT_EOF 1>&2
2771
2772*** Warning: the command libtool uses to detect shared libraries,
2773*** $file_magic_cmd, produces output that libtool cannot recognize.
2774*** The result is that libtool may fail to recognize shared libraries
2775*** as such. This will affect the creation of libtool libraries that
2776*** depend on shared libraries, but programs linked with such libtool
2777*** libraries will work regardless of this problem. Nevertheless, you
2778*** may want to report the problem to your system manager and/or to
2779*** bug-libtool@gnu.org
2780
2781_LT_EOF
2782 fi ;;
2783 esac
2784 fi
2785 break
2786 fi
2787 done
2788 IFS="$lt_save_ifs"
2789 MAGIC_CMD="$lt_save_MAGIC_CMD"
2790 ;;
2791esac])
2792MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
2793if test -n "$MAGIC_CMD"; then
2794 AC_MSG_RESULT($MAGIC_CMD)
2795else
2796 AC_MSG_RESULT(no)
2797fi
2798_LT_DECL([], [MAGIC_CMD], [0],
2799 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
2800])# _LT_PATH_TOOL_PREFIX
2801
2802# Old name:
2803AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
2804dnl aclocal-1.4 backwards compatibility:
2805dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
2806
2807
2808# _LT_PATH_MAGIC
2809# --------------
2810# find a file program which can recognize a shared library
2811m4_defun([_LT_PATH_MAGIC],
2812[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
2813if test -z "$lt_cv_path_MAGIC_CMD"; then
2814 if test -n "$ac_tool_prefix"; then
2815 _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
2816 else
2817 MAGIC_CMD=:
2818 fi
2819fi
2820])# _LT_PATH_MAGIC
2821
2822
2823# LT_PATH_LD
2824# ----------
2825# find the pathname to the GNU or non-GNU linker
2826AC_DEFUN([LT_PATH_LD],
2827[AC_REQUIRE([AC_PROG_CC])dnl
2828AC_REQUIRE([AC_CANONICAL_HOST])dnl
2829AC_REQUIRE([AC_CANONICAL_BUILD])dnl
2830m4_require([_LT_DECL_SED])dnl
2831m4_require([_LT_DECL_EGREP])dnl
2832
2833AC_ARG_WITH([gnu-ld],
2834 [AS_HELP_STRING([--with-gnu-ld],
2835 [assume the C compiler uses GNU ld @<:@default=no@:>@])],
2836 [test "$withval" = no || with_gnu_ld=yes],
2837 [with_gnu_ld=no])dnl
2838
2839ac_prog=ld
2840if test "$GCC" = yes; then
2841 # Check if gcc -print-prog-name=ld gives a path.
2842 AC_MSG_CHECKING([for ld used by $CC])
2843 case $host in
2844 *-*-mingw*)
2845 # gcc leaves a trailing carriage return which upsets mingw
2846 ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
2847 *)
2848 ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
2849 esac
2850 case $ac_prog in
2851 # Accept absolute paths.
2852 [[\\/]]* | ?:[[\\/]]*)
2853 re_direlt='/[[^/]][[^/]]*/\.\./'
2854 # Canonicalize the pathname of ld
2855 ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
2856 while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
2857 ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
2858 done
2859 test -z "$LD" && LD="$ac_prog"
2860 ;;
2861 "")
2862 # If it fails, then pretend we aren't using GCC.
2863 ac_prog=ld
2864 ;;
2865 *)
2866 # If it is relative, then search for the first ld in PATH.
2867 with_gnu_ld=unknown
2868 ;;
2869 esac
2870elif test "$with_gnu_ld" = yes; then
2871 AC_MSG_CHECKING([for GNU ld])
2872else
2873 AC_MSG_CHECKING([for non-GNU ld])
2874fi
2875AC_CACHE_VAL(lt_cv_path_LD,
2876[if test -z "$LD"; then
2877 lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
2878 for ac_dir in $PATH; do
2879 IFS="$lt_save_ifs"
2880 test -z "$ac_dir" && ac_dir=.
2881 if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
2882 lt_cv_path_LD="$ac_dir/$ac_prog"
2883 # Check to see if the program is GNU ld. I'd rather use --version,
2884 # but apparently some variants of GNU ld only accept -v.
2885 # Break only if it was the GNU/non-GNU ld that we prefer.
2886 case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
2887 *GNU* | *'with BFD'*)
2888 test "$with_gnu_ld" != no && break
2889 ;;
2890 *)
2891 test "$with_gnu_ld" != yes && break
2892 ;;
2893 esac
2894 fi
2895 done
2896 IFS="$lt_save_ifs"
2897else
2898 lt_cv_path_LD="$LD" # Let the user override the test with a path.
2899fi])
2900LD="$lt_cv_path_LD"
2901if test -n "$LD"; then
2902 AC_MSG_RESULT($LD)
2903else
2904 AC_MSG_RESULT(no)
2905fi
2906test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
2907_LT_PATH_LD_GNU
2908AC_SUBST([LD])
2909
2910_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
2911])# LT_PATH_LD
2912
2913# Old names:
2914AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
2915AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
2916dnl aclocal-1.4 backwards compatibility:
2917dnl AC_DEFUN([AM_PROG_LD], [])
2918dnl AC_DEFUN([AC_PROG_LD], [])
2919
2920
2921# _LT_PATH_LD_GNU
2922#- --------------
2923m4_defun([_LT_PATH_LD_GNU],
2924[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
2925[# I'd rather use --version here, but apparently some GNU lds only accept -v.
2926case `$LD -v 2>&1 </dev/null` in
2927*GNU* | *'with BFD'*)
2928 lt_cv_prog_gnu_ld=yes
2929 ;;
2930*)
2931 lt_cv_prog_gnu_ld=no
2932 ;;
2933esac])
2934with_gnu_ld=$lt_cv_prog_gnu_ld
2935])# _LT_PATH_LD_GNU
2936
2937
2938# _LT_CMD_RELOAD
2939# --------------
2940# find reload flag for linker
2941# -- PORTME Some linkers may need a different reload flag.
2942m4_defun([_LT_CMD_RELOAD],
2943[AC_CACHE_CHECK([for $LD option to reload object files],
2944 lt_cv_ld_reload_flag,
2945 [lt_cv_ld_reload_flag='-r'])
2946reload_flag=$lt_cv_ld_reload_flag
2947case $reload_flag in
2948"" | " "*) ;;
2949*) reload_flag=" $reload_flag" ;;
2950esac
2951reload_cmds='$LD$reload_flag -o $output$reload_objs'
2952case $host_os in
2953 darwin*)
2954 if test "$GCC" = yes; then
2955 reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
2956 else
2957 reload_cmds='$LD$reload_flag -o $output$reload_objs'
2958 fi
2959 ;;
2960esac
2961_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
2962_LT_DECL([], [reload_cmds], [2])dnl
2963])# _LT_CMD_RELOAD
2964
2965
2966# _LT_CHECK_MAGIC_METHOD
2967# ----------------------
2968# how to check for library dependencies
2969# -- PORTME fill in with the dynamic library characteristics
2970m4_defun([_LT_CHECK_MAGIC_METHOD],
2971[m4_require([_LT_DECL_EGREP])
2972m4_require([_LT_DECL_OBJDUMP])
2973AC_CACHE_CHECK([how to recognize dependent libraries],
2974lt_cv_deplibs_check_method,
2975[lt_cv_file_magic_cmd='$MAGIC_CMD'
2976lt_cv_file_magic_test_file=
2977lt_cv_deplibs_check_method='unknown'
2978# Need to set the preceding variable on all platforms that support
2979# interlibrary dependencies.
2980# 'none' -- dependencies not supported.
2981# `unknown' -- same as none, but documents that we really don't know.
2982# 'pass_all' -- all dependencies passed with no checks.
2983# 'test_compile' -- check by making test program.
2984# 'file_magic [[regex]]' -- check by looking for files in library path
2985# which responds to the $file_magic_cmd with a given extended regex.
2986# If you have `file' or equivalent on your system and you're not sure
2987# whether `pass_all' will *always* work, you probably want this one.
2988
2989case $host_os in
2990aix[[4-9]]*)
2991 lt_cv_deplibs_check_method=pass_all
2992 ;;
2993
2994beos*)
2995 lt_cv_deplibs_check_method=pass_all
2996 ;;
2997
2998bsdi[[45]]*)
2999 lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
3000 lt_cv_file_magic_cmd='/usr/bin/file -L'
3001 lt_cv_file_magic_test_file=/shlib/libc.so
3002 ;;
3003
3004cygwin*)
3005 # func_win32_libid is a shell function defined in ltmain.sh
3006 lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
3007 lt_cv_file_magic_cmd='func_win32_libid'
3008 ;;
3009
3010mingw* | pw32*)
3011 # Base MSYS/MinGW do not provide the 'file' command needed by
3012 # func_win32_libid shell function, so use a weaker test based on 'objdump',
3013 # unless we find 'file', for example because we are cross-compiling.
3014 if ( file / ) >/dev/null 2>&1; then
3015 lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
3016 lt_cv_file_magic_cmd='func_win32_libid'
3017 else
3018 lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
3019 lt_cv_file_magic_cmd='$OBJDUMP -f'
3020 fi
3021 ;;
3022
3023cegcc)
3024 # use the weaker test based on 'objdump'. See mingw*.
3025 lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
3026 lt_cv_file_magic_cmd='$OBJDUMP -f'
3027 ;;
3028
3029darwin* | rhapsody*)
3030 lt_cv_deplibs_check_method=pass_all
3031 ;;
3032
3033freebsd* | dragonfly*)
3034 if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
3035 case $host_cpu in
3036 i*86 )
3037 # Not sure whether the presence of OpenBSD here was a mistake.
3038 # Let's accept both of them until this is cleared up.
3039 lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
3040 lt_cv_file_magic_cmd=/usr/bin/file
3041 lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
3042 ;;
3043 esac
3044 else
3045 lt_cv_deplibs_check_method=pass_all
3046 fi
3047 ;;
3048
3049gnu*)
3050 lt_cv_deplibs_check_method=pass_all
3051 ;;
3052
3053hpux10.20* | hpux11*)
3054 lt_cv_file_magic_cmd=/usr/bin/file
3055 case $host_cpu in
3056 ia64*)
3057 lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
3058 lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
3059 ;;
3060 hppa*64*)
3061 [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
3062 lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
3063 ;;
3064 *)
3065 lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
3066 lt_cv_file_magic_test_file=/usr/lib/libc.sl
3067 ;;
3068 esac
3069 ;;
3070
3071interix[[3-9]]*)
3072 # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
3073 lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
3074 ;;
3075
3076irix5* | irix6* | nonstopux*)
3077 case $LD in
3078 *-32|*"-32 ") libmagic=32-bit;;
3079 *-n32|*"-n32 ") libmagic=N32;;
3080 *-64|*"-64 ") libmagic=64-bit;;
3081 *) libmagic=never-match;;
3082 esac
3083 lt_cv_deplibs_check_method=pass_all
3084 ;;
3085
3086# This must be Linux ELF.
3087linux* | k*bsd*-gnu | kopensolaris*-gnu)
3088 lt_cv_deplibs_check_method=pass_all
3089 ;;
3090
3091netbsd* | netbsdelf*-gnu)
3092 if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
3093 lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
3094 else
3095 lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
3096 fi
3097 ;;
3098
3099newos6*)
3100 lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
3101 lt_cv_file_magic_cmd=/usr/bin/file
3102 lt_cv_file_magic_test_file=/usr/lib/libnls.so
3103 ;;
3104
3105*nto* | *qnx*)
3106 lt_cv_deplibs_check_method=pass_all
3107 ;;
3108
3109openbsd*)
3110 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
3111 lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
3112 else
3113 lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
3114 fi
3115 ;;
3116
3117osf3* | osf4* | osf5*)
3118 lt_cv_deplibs_check_method=pass_all
3119 ;;
3120
3121rdos*)
3122 lt_cv_deplibs_check_method=pass_all
3123 ;;
3124
3125solaris*)
3126 lt_cv_deplibs_check_method=pass_all
3127 ;;
3128
3129sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
3130 lt_cv_deplibs_check_method=pass_all
3131 ;;
3132
3133sysv4 | sysv4.3*)
3134 case $host_vendor in
3135 motorola)
3136 lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
3137 lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
3138 ;;
3139 ncr)
3140 lt_cv_deplibs_check_method=pass_all
3141 ;;
3142 sequent)
3143 lt_cv_file_magic_cmd='/bin/file'
3144 lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
3145 ;;
3146 sni)
3147 lt_cv_file_magic_cmd='/bin/file'
3148 lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
3149 lt_cv_file_magic_test_file=/lib/libc.so
3150 ;;
3151 siemens)
3152 lt_cv_deplibs_check_method=pass_all
3153 ;;
3154 pc)
3155 lt_cv_deplibs_check_method=pass_all
3156 ;;
3157 esac
3158 ;;
3159
3160tpf*)
3161 lt_cv_deplibs_check_method=pass_all
3162 ;;
3163esac
3164])
3165file_magic_cmd=$lt_cv_file_magic_cmd
3166deplibs_check_method=$lt_cv_deplibs_check_method
3167test -z "$deplibs_check_method" && deplibs_check_method=unknown
3168
3169_LT_DECL([], [deplibs_check_method], [1],
3170 [Method to check whether dependent libraries are shared objects])
3171_LT_DECL([], [file_magic_cmd], [1],
3172 [Command to use when deplibs_check_method == "file_magic"])
3173])# _LT_CHECK_MAGIC_METHOD
3174
3175
3176# LT_PATH_NM
3177# ----------
3178# find the pathname to a BSD- or MS-compatible name lister
3179AC_DEFUN([LT_PATH_NM],
3180[AC_REQUIRE([AC_PROG_CC])dnl
3181AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
3182[if test -n "$NM"; then
3183 # Let the user override the test.
3184 lt_cv_path_NM="$NM"
3185else
3186 lt_nm_to_check="${ac_tool_prefix}nm"
3187 if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
3188 lt_nm_to_check="$lt_nm_to_check nm"
3189 fi
3190 for lt_tmp_nm in $lt_nm_to_check; do
3191 lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
3192 for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
3193 IFS="$lt_save_ifs"
3194 test -z "$ac_dir" && ac_dir=.
3195 tmp_nm="$ac_dir/$lt_tmp_nm"
3196 if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
3197 # Check to see if the nm accepts a BSD-compat flag.
3198 # Adding the `sed 1q' prevents false positives on HP-UX, which says:
3199 # nm: unknown option "B" ignored
3200 # Tru64's nm complains that /dev/null is an invalid object file
3201 case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
3202 */dev/null* | *'Invalid file or object type'*)
3203 lt_cv_path_NM="$tmp_nm -B"
3204 break
3205 ;;
3206 *)
3207 case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
3208 */dev/null*)
3209 lt_cv_path_NM="$tmp_nm -p"
3210 break
3211 ;;
3212 *)
3213 lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
3214 continue # so that we can try to find one that supports BSD flags
3215 ;;
3216 esac
3217 ;;
3218 esac
3219 fi
3220 done
3221 IFS="$lt_save_ifs"
3222 done
3223 : ${lt_cv_path_NM=no}
3224fi])
3225if test "$lt_cv_path_NM" != "no"; then
3226 NM="$lt_cv_path_NM"
3227else
3228 # Didn't find any BSD compatible name lister, look for dumpbin.
3229 AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
3230 AC_SUBST([DUMPBIN])
3231 if test "$DUMPBIN" != ":"; then
3232 NM="$DUMPBIN"
3233 fi
3234fi
3235test -z "$NM" && NM=nm
3236AC_SUBST([NM])
3237_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
3238
3239AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
3240 [lt_cv_nm_interface="BSD nm"
3241 echo "int some_variable = 0;" > conftest.$ac_ext
3242 (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
3243 (eval "$ac_compile" 2>conftest.err)
3244 cat conftest.err >&AS_MESSAGE_LOG_FD
3245 (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
3246 (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
3247 cat conftest.err >&AS_MESSAGE_LOG_FD
3248 (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
3249 cat conftest.out >&AS_MESSAGE_LOG_FD
3250 if $GREP 'External.*some_variable' conftest.out > /dev/null; then
3251 lt_cv_nm_interface="MS dumpbin"
3252 fi
3253 rm -f conftest*])
3254])# LT_PATH_NM
3255
3256# Old names:
3257AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
3258AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
3259dnl aclocal-1.4 backwards compatibility:
3260dnl AC_DEFUN([AM_PROG_NM], [])
3261dnl AC_DEFUN([AC_PROG_NM], [])
3262
3263
3264# LT_LIB_M
3265# --------
3266# check for math library
3267AC_DEFUN([LT_LIB_M],
3268[AC_REQUIRE([AC_CANONICAL_HOST])dnl
3269LIBM=
3270case $host in
3271*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
3272 # These system don't have libm, or don't need it
3273 ;;
3274*-ncr-sysv4.3*)
3275 AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
3276 AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
3277 ;;
3278*)
3279 AC_CHECK_LIB(m, cos, LIBM="-lm")
3280 ;;
3281esac
3282AC_SUBST([LIBM])
3283])# LT_LIB_M
3284
3285# Old name:
3286AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
3287dnl aclocal-1.4 backwards compatibility:
3288dnl AC_DEFUN([AC_CHECK_LIBM], [])
3289
3290
3291# _LT_COMPILER_NO_RTTI([TAGNAME])
3292# -------------------------------
3293m4_defun([_LT_COMPILER_NO_RTTI],
3294[m4_require([_LT_TAG_COMPILER])dnl
3295
3296_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
3297
3298if test "$GCC" = yes; then
3299 _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
3300
3301 _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
3302 lt_cv_prog_compiler_rtti_exceptions,
3303 [-fno-rtti -fno-exceptions], [],
3304 [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
3305fi
3306_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
3307 [Compiler flag to turn off builtin functions])
3308])# _LT_COMPILER_NO_RTTI
3309
3310
3311# _LT_CMD_GLOBAL_SYMBOLS
3312# ----------------------
3313m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
3314[AC_REQUIRE([AC_CANONICAL_HOST])dnl
3315AC_REQUIRE([AC_PROG_CC])dnl
3316AC_REQUIRE([LT_PATH_NM])dnl
3317AC_REQUIRE([LT_PATH_LD])dnl
3318m4_require([_LT_DECL_SED])dnl
3319m4_require([_LT_DECL_EGREP])dnl
3320m4_require([_LT_TAG_COMPILER])dnl
3321
3322# Check for command to grab the raw symbol name followed by C symbol from nm.
3323AC_MSG_CHECKING([command to parse $NM output from $compiler object])
3324AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
3325[
3326# These are sane defaults that work on at least a few old systems.
3327# [They come from Ultrix. What could be older than Ultrix?!! ;)]
3328
3329# Character class describing NM global symbol codes.
3330symcode='[[BCDEGRST]]'
3331
3332# Regexp to match symbols that can be accessed directly from C.
3333sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
3334
3335# Define system-specific variables.
3336case $host_os in
3337aix*)
3338 symcode='[[BCDT]]'
3339 ;;
3340cygwin* | mingw* | pw32* | cegcc*)
3341 symcode='[[ABCDGISTW]]'
3342 ;;
3343hpux*)
3344 if test "$host_cpu" = ia64; then
3345 symcode='[[ABCDEGRST]]'
3346 fi
3347 ;;
3348irix* | nonstopux*)
3349 symcode='[[BCDEGRST]]'
3350 ;;
3351osf*)
3352 symcode='[[BCDEGQRST]]'
3353 ;;
3354solaris*)
3355 symcode='[[BDRT]]'
3356 ;;
3357sco3.2v5*)
3358 symcode='[[DT]]'
3359 ;;
3360sysv4.2uw2*)
3361 symcode='[[DT]]'
3362 ;;
3363sysv5* | sco5v6* | unixware* | OpenUNIX*)
3364 symcode='[[ABDT]]'
3365 ;;
3366sysv4)
3367 symcode='[[DFNSTU]]'
3368 ;;
3369esac
3370
3371# If we're using GNU nm, then use its standard symbol codes.
3372case `$NM -V 2>&1` in
3373*GNU* | *'with BFD'*)
3374 symcode='[[ABCDGIRSTW]]' ;;
3375esac
3376
3377# Transform an extracted symbol line into a proper C declaration.
3378# Some systems (esp. on ia64) link data and code symbols differently,
3379# so use this general approach.
3380lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
3381
3382# Transform an extracted symbol line into symbol name and symbol address
3383lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
3384lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
3385
3386# Handle CRLF in mingw tool chain
3387opt_cr=
3388case $build_os in
3389mingw*)
3390 opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
3391 ;;
3392esac
3393
3394# Try without a prefix underscore, then with it.
3395for ac_symprfx in "" "_"; do
3396
3397 # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
3398 symxfrm="\\1 $ac_symprfx\\2 \\2"
3399
3400 # Write the raw and C identifiers.
3401 if test "$lt_cv_nm_interface" = "MS dumpbin"; then
3402 # Fake it for dumpbin and say T for any non-static function
3403 # and D for any global variable.
3404 # Also find C++ and __fastcall symbols from MSVC++,
3405 # which start with @ or ?.
3406 lt_cv_sys_global_symbol_pipe="$AWK ['"\
3407" {last_section=section; section=\$ 3};"\
3408" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
3409" \$ 0!~/External *\|/{next};"\
3410" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
3411" {if(hide[section]) next};"\
3412" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
3413" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
3414" s[1]~/^[@?]/{print s[1], s[1]; next};"\
3415" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
3416" ' prfx=^$ac_symprfx]"
3417 else
3418 lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
3419 fi
3420
3421 # Check to see that the pipe works correctly.
3422 pipe_works=no
3423
3424 rm -f conftest*
3425 cat > conftest.$ac_ext <<_LT_EOF
3426#ifdef __cplusplus
3427extern "C" {
3428#endif
3429char nm_test_var;
3430void nm_test_func(void);
3431void nm_test_func(void){}
3432#ifdef __cplusplus
3433}
3434#endif
3435int main(){nm_test_var='a';nm_test_func();return(0);}
3436_LT_EOF
3437
3438 if AC_TRY_EVAL(ac_compile); then
3439 # Now try to grab the symbols.
3440 nlist=conftest.nm
3441 if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
3442 # Try sorting and uniquifying the output.
3443 if sort "$nlist" | uniq > "$nlist"T; then
3444 mv -f "$nlist"T "$nlist"
3445 else
3446 rm -f "$nlist"T
3447 fi
3448
3449 # Make sure that we snagged all the symbols we need.
3450 if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
3451 if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
3452 cat <<_LT_EOF > conftest.$ac_ext
3453#ifdef __cplusplus
3454extern "C" {
3455#endif
3456
3457_LT_EOF
3458 # Now generate the symbol file.
3459 eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
3460
3461 cat <<_LT_EOF >> conftest.$ac_ext
3462
3463/* The mapping between symbol names and symbols. */
3464const struct {
3465 const char *name;
3466 void *address;
3467}
3468lt__PROGRAM__LTX_preloaded_symbols[[]] =
3469{
3470 { "@PROGRAM@", (void *) 0 },
3471_LT_EOF
3472 $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
3473 cat <<\_LT_EOF >> conftest.$ac_ext
3474 {0, (void *) 0}
3475};
3476
3477/* This works around a problem in FreeBSD linker */
3478#ifdef FREEBSD_WORKAROUND
3479static const void *lt_preloaded_setup() {
3480 return lt__PROGRAM__LTX_preloaded_symbols;
3481}
3482#endif
3483
3484#ifdef __cplusplus
3485}
3486#endif
3487_LT_EOF
3488 # Now try linking the two files.
3489 mv conftest.$ac_objext conftstm.$ac_objext
3490 lt_save_LIBS="$LIBS"
3491 lt_save_CFLAGS="$CFLAGS"
3492 LIBS="conftstm.$ac_objext"
3493 CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
3494 if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
3495 pipe_works=yes
3496 fi
3497 LIBS="$lt_save_LIBS"
3498 CFLAGS="$lt_save_CFLAGS"
3499 else
3500 echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
3501 fi
3502 else
3503 echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
3504 fi
3505 else
3506 echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
3507 fi
3508 else
3509 echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
3510 cat conftest.$ac_ext >&5
3511 fi
3512 rm -rf conftest* conftst*
3513
3514 # Do not use the global_symbol_pipe unless it works.
3515 if test "$pipe_works" = yes; then
3516 break
3517 else
3518 lt_cv_sys_global_symbol_pipe=
3519 fi
3520done
3521])
3522if test -z "$lt_cv_sys_global_symbol_pipe"; then
3523 lt_cv_sys_global_symbol_to_cdecl=
3524fi
3525if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
3526 AC_MSG_RESULT(failed)
3527else
3528 AC_MSG_RESULT(ok)
3529fi
3530
3531_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
3532 [Take the output of nm and produce a listing of raw symbols and C names])
3533_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
3534 [Transform the output of nm in a proper C declaration])
3535_LT_DECL([global_symbol_to_c_name_address],
3536 [lt_cv_sys_global_symbol_to_c_name_address], [1],
3537 [Transform the output of nm in a C name address pair])
3538_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
3539 [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
3540 [Transform the output of nm in a C name address pair when lib prefix is needed])
3541]) # _LT_CMD_GLOBAL_SYMBOLS
3542
3543
3544# _LT_COMPILER_PIC([TAGNAME])
3545# ---------------------------
3546m4_defun([_LT_COMPILER_PIC],
3547[m4_require([_LT_TAG_COMPILER])dnl
3548_LT_TAGVAR(lt_prog_compiler_wl, $1)=
3549_LT_TAGVAR(lt_prog_compiler_pic, $1)=
3550_LT_TAGVAR(lt_prog_compiler_static, $1)=
3551
3552AC_MSG_CHECKING([for $compiler option to produce PIC])
3553m4_if([$1], [CXX], [
3554 # C++ specific cases for pic, static, wl, etc.
3555 if test "$GXX" = yes; then
3556 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3557 _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
3558
3559 case $host_os in
3560 aix*)
3561 # All AIX code is PIC.
3562 if test "$host_cpu" = ia64; then
3563 # AIX 5 now supports IA64 processor
3564 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3565 fi
3566 ;;
3567
3568 amigaos*)
3569 case $host_cpu in
3570 powerpc)
3571 # see comment about AmigaOS4 .so support
3572 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3573 ;;
3574 m68k)
3575 # FIXME: we need at least 68020 code to build shared libraries, but
3576 # adding the `-m68020' flag to GCC prevents building anything better,
3577 # like `-m68040'.
3578 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
3579 ;;
3580 esac
3581 ;;
3582
3583 beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
3584 # PIC is the default for these OSes.
3585 ;;
3586 mingw* | cygwin* | os2* | pw32* | cegcc*)
3587 # This hack is so that the source file can tell whether it is being
3588 # built for inclusion in a dll (and should export symbols for example).
3589 # Although the cygwin gcc ignores -fPIC, still need this for old-style
3590 # (--disable-auto-import) libraries
3591 m4_if([$1], [GCJ], [],
3592 [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
3593 ;;
3594 darwin* | rhapsody*)
3595 # PIC is the default on this platform
3596 # Common symbols not allowed in MH_DYLIB files
3597 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
3598 ;;
3599 *djgpp*)
3600 # DJGPP does not support shared libraries at all
3601 _LT_TAGVAR(lt_prog_compiler_pic, $1)=
3602 ;;
3603 interix[[3-9]]*)
3604 # Interix 3.x gcc -fpic/-fPIC options generate broken code.
3605 # Instead, we relocate shared libraries at runtime.
3606 ;;
3607 sysv4*MP*)
3608 if test -d /usr/nec; then
3609 _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
3610 fi
3611 ;;
3612 hpux*)
3613 # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
3614 # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
3615 # sets the default TLS model and affects inlining.
3616 case $host_cpu in
3617 hppa*64*)
3618 ;;
3619 *)
3620 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3621 ;;
3622 esac
3623 ;;
3624 *qnx* | *nto*)
3625 # QNX uses GNU C++, but need to define -shared option too, otherwise
3626 # it will coredump.
3627 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
3628 ;;
3629 *)
3630 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3631 ;;
3632 esac
3633 else
3634 case $host_os in
3635 aix[[4-9]]*)
3636 # All AIX code is PIC.
3637 if test "$host_cpu" = ia64; then
3638 # AIX 5 now supports IA64 processor
3639 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3640 else
3641 _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
3642 fi
3643 ;;
3644 chorus*)
3645 case $cc_basename in
3646 cxch68*)
3647 # Green Hills C++ Compiler
3648 # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
3649 ;;
3650 esac
3651 ;;
3652 dgux*)
3653 case $cc_basename in
3654 ec++*)
3655 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3656 ;;
3657 ghcx*)
3658 # Green Hills C++ Compiler
3659 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
3660 ;;
3661 *)
3662 ;;
3663 esac
3664 ;;
3665 freebsd* | dragonfly*)
3666 # FreeBSD uses GNU C++
3667 ;;
3668 hpux9* | hpux10* | hpux11*)
3669 case $cc_basename in
3670 CC*)
3671 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3672 _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
3673 if test "$host_cpu" != ia64; then
3674 _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
3675 fi
3676 ;;
3677 aCC*)
3678 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3679 _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
3680 case $host_cpu in
3681 hppa*64*|ia64*)
3682 # +Z the default
3683 ;;
3684 *)
3685 _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
3686 ;;
3687 esac
3688 ;;
3689 *)
3690 ;;
3691 esac
3692 ;;
3693 interix*)
3694 # This is c89, which is MS Visual C++ (no shared libs)
3695 # Anyone wants to do a port?
3696 ;;
3697 irix5* | irix6* | nonstopux*)
3698 case $cc_basename in
3699 CC*)
3700 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3701 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
3702 # CC pic flag -KPIC is the default.
3703 ;;
3704 *)
3705 ;;
3706 esac
3707 ;;
3708 linux* | k*bsd*-gnu | kopensolaris*-gnu)
3709 case $cc_basename in
3710 KCC*)
3711 # KAI C++ Compiler
3712 _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
3713 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3714 ;;
3715 ecpc* )
3716 # old Intel C++ for x86_64 which still supported -KPIC.
3717 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3718 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3719 _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
3720 ;;
3721 icpc* )
3722 # Intel C++, used to be incompatible with GCC.
3723 # ICC 10 doesn't accept -KPIC any more.
3724 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3725 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3726 _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
3727 ;;
3728 pgCC* | pgcpp*)
3729 # Portland Group C++ compiler
3730 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3731 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
3732 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3733 ;;
3734 cxx*)
3735 # Compaq C++
3736 # Make sure the PIC flag is empty. It appears that all Alpha
3737 # Linux and Compaq Tru64 Unix objects are PIC.
3738 _LT_TAGVAR(lt_prog_compiler_pic, $1)=
3739 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
3740 ;;
3741 xlc* | xlC*)
3742 # IBM XL 8.0 on PPC
3743 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3744 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
3745 _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
3746 ;;
3747 *)
3748 case `$CC -V 2>&1 | sed 5q` in
3749 *Sun\ C*)
3750 # Sun C++ 5.9
3751 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3752 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3753 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
3754 ;;
3755 esac
3756 ;;
3757 esac
3758 ;;
3759 lynxos*)
3760 ;;
3761 m88k*)
3762 ;;
3763 mvs*)
3764 case $cc_basename in
3765 cxx*)
3766 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
3767 ;;
3768 *)
3769 ;;
3770 esac
3771 ;;
3772 netbsd* | netbsdelf*-gnu)
3773 ;;
3774 *qnx* | *nto*)
3775 # QNX uses GNU C++, but need to define -shared option too, otherwise
3776 # it will coredump.
3777 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
3778 ;;
3779 osf3* | osf4* | osf5*)
3780 case $cc_basename in
3781 KCC*)
3782 _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
3783 ;;
3784 RCC*)
3785 # Rational C++ 2.4.1
3786 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
3787 ;;
3788 cxx*)
3789 # Digital/Compaq C++
3790 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3791 # Make sure the PIC flag is empty. It appears that all Alpha
3792 # Linux and Compaq Tru64 Unix objects are PIC.
3793 _LT_TAGVAR(lt_prog_compiler_pic, $1)=
3794 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
3795 ;;
3796 *)
3797 ;;
3798 esac
3799 ;;
3800 psos*)
3801 ;;
3802 solaris*)
3803 case $cc_basename in
3804 CC*)
3805 # Sun C++ 4.2, 5.x and Centerline C++
3806 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3807 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3808 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
3809 ;;
3810 gcx*)
3811 # Green Hills C++ Compiler
3812 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
3813 ;;
3814 *)
3815 ;;
3816 esac
3817 ;;
3818 sunos4*)
3819 case $cc_basename in
3820 CC*)
3821 # Sun C++ 4.x
3822 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
3823 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3824 ;;
3825 lcc*)
3826 # Lucid
3827 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
3828 ;;
3829 *)
3830 ;;
3831 esac
3832 ;;
3833 sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
3834 case $cc_basename in
3835 CC*)
3836 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3837 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3838 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3839 ;;
3840 esac
3841 ;;
3842 tandem*)
3843 case $cc_basename in
3844 NCC*)
3845 # NonStop-UX NCC 3.20
3846 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3847 ;;
3848 *)
3849 ;;
3850 esac
3851 ;;
3852 vxworks*)
3853 ;;
3854 *)
3855 _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
3856 ;;
3857 esac
3858 fi
3859],
3860[
3861 if test "$GCC" = yes; then
3862 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3863 _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
3864
3865 case $host_os in
3866 aix*)
3867 # All AIX code is PIC.
3868 if test "$host_cpu" = ia64; then
3869 # AIX 5 now supports IA64 processor
3870 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3871 fi
3872 ;;
3873
3874 amigaos*)
3875 case $host_cpu in
3876 powerpc)
3877 # see comment about AmigaOS4 .so support
3878 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3879 ;;
3880 m68k)
3881 # FIXME: we need at least 68020 code to build shared libraries, but
3882 # adding the `-m68020' flag to GCC prevents building anything better,
3883 # like `-m68040'.
3884 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
3885 ;;
3886 esac
3887 ;;
3888
3889 beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
3890 # PIC is the default for these OSes.
3891 ;;
3892
3893 mingw* | cygwin* | pw32* | os2* | cegcc*)
3894 # This hack is so that the source file can tell whether it is being
3895 # built for inclusion in a dll (and should export symbols for example).
3896 # Although the cygwin gcc ignores -fPIC, still need this for old-style
3897 # (--disable-auto-import) libraries
3898 m4_if([$1], [GCJ], [],
3899 [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
3900 ;;
3901
3902 darwin* | rhapsody*)
3903 # PIC is the default on this platform
3904 # Common symbols not allowed in MH_DYLIB files
3905 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
3906 ;;
3907
3908 hpux*)
3909 # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
3910 # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
3911 # sets the default TLS model and affects inlining.
3912 case $host_cpu in
3913 hppa*64*)
3914 # +Z the default
3915 ;;
3916 *)
3917 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3918 ;;
3919 esac
3920 ;;
3921
3922 interix[[3-9]]*)
3923 # Interix 3.x gcc -fpic/-fPIC options generate broken code.
3924 # Instead, we relocate shared libraries at runtime.
3925 ;;
3926
3927 msdosdjgpp*)
3928 # Just because we use GCC doesn't mean we suddenly get shared libraries
3929 # on systems that don't support them.
3930 _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
3931 enable_shared=no
3932 ;;
3933
3934 *nto* | *qnx*)
3935 # QNX uses GNU C++, but need to define -shared option too, otherwise
3936 # it will coredump.
3937 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
3938 ;;
3939
3940 sysv4*MP*)
3941 if test -d /usr/nec; then
3942 _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
3943 fi
3944 ;;
3945
3946 *)
3947 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
3948 ;;
3949 esac
3950 else
3951 # PORTME Check for flag to pass linker flags through the system compiler.
3952 case $host_os in
3953 aix*)
3954 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3955 if test "$host_cpu" = ia64; then
3956 # AIX 5 now supports IA64 processor
3957 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
3958 else
3959 _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
3960 fi
3961 ;;
3962
3963 mingw* | cygwin* | pw32* | os2* | cegcc*)
3964 # This hack is so that the source file can tell whether it is being
3965 # built for inclusion in a dll (and should export symbols for example).
3966 m4_if([$1], [GCJ], [],
3967 [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
3968 ;;
3969
3970 hpux9* | hpux10* | hpux11*)
3971 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3972 # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
3973 # not for PA HP-UX.
3974 case $host_cpu in
3975 hppa*64*|ia64*)
3976 # +Z the default
3977 ;;
3978 *)
3979 _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
3980 ;;
3981 esac
3982 # Is there a better lt_prog_compiler_static that works with the bundled CC?
3983 _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
3984 ;;
3985
3986 irix5* | irix6* | nonstopux*)
3987 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3988 # PIC (with -KPIC) is the default.
3989 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
3990 ;;
3991
3992 linux* | k*bsd*-gnu | kopensolaris*-gnu)
3993 case $cc_basename in
3994 # old Intel for x86_64 which still supported -KPIC.
3995 ecc*)
3996 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
3997 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
3998 _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
3999 ;;
4000 # icc used to be incompatible with GCC.
4001 # ICC 10 doesn't accept -KPIC any more.
4002 icc* | ifort*)
4003 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4004 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
4005 _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
4006 ;;
4007 # Lahey Fortran 8.1.
4008 lf95*)
4009 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4010 _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
4011 _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
4012 ;;
4013 pgcc* | pgf77* | pgf90* | pgf95*)
4014 # Portland Group compilers (*not* the Pentium gcc compiler,
4015 # which looks to be a dead project)
4016 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4017 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
4018 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4019 ;;
4020 ccc*)
4021 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4022 # All Alpha code is PIC.
4023 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
4024 ;;
4025 xl*)
4026 # IBM XL C 8.0/Fortran 10.1 on PPC
4027 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4028 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
4029 _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
4030 ;;
4031 *)
4032 case `$CC -V 2>&1 | sed 5q` in
4033 *Sun\ C*)
4034 # Sun C 5.9
4035 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
4036 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4037 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4038 ;;
4039 *Sun\ F*)
4040 # Sun Fortran 8.3 passes all unrecognized flags to the linker
4041 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
4042 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4043 _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
4044 ;;
4045 esac
4046 ;;
4047 esac
4048 ;;
4049
4050 newsos6)
4051 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
4052 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4053 ;;
4054
4055 *nto* | *qnx*)
4056 # QNX uses GNU C++, but need to define -shared option too, otherwise
4057 # it will coredump.
4058 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
4059 ;;
4060
4061 osf3* | osf4* | osf5*)
4062 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4063 # All OSF/1 code is PIC.
4064 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
4065 ;;
4066
4067 rdos*)
4068 _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
4069 ;;
4070
4071 solaris*)
4072 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
4073 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4074 case $cc_basename in
4075 f77* | f90* | f95*)
4076 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
4077 *)
4078 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
4079 esac
4080 ;;
4081
4082 sunos4*)
4083 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
4084 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
4085 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4086 ;;
4087
4088 sysv4 | sysv4.2uw2* | sysv4.3*)
4089 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4090 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
4091 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4092 ;;
4093
4094 sysv4*MP*)
4095 if test -d /usr/nec ;then
4096 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
4097 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4098 fi
4099 ;;
4100
4101 sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
4102 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4103 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
4104 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4105 ;;
4106
4107 unicos*)
4108 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
4109 _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
4110 ;;
4111
4112 uts4*)
4113 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
4114 _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
4115 ;;
4116
4117 *)
4118 _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
4119 ;;
4120 esac
4121 fi
4122])
4123case $host_os in
4124 # For platforms which do not support PIC, -DPIC is meaningless:
4125 *djgpp*)
4126 _LT_TAGVAR(lt_prog_compiler_pic, $1)=
4127 ;;
4128 *)
4129 _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
4130 ;;
4131esac
4132AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
4133_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
4134 [How to pass a linker flag through the compiler])
4135
4136#
4137# Check to make sure the PIC flag actually works.
4138#
4139if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
4140 _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
4141 [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
4142 [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
4143 [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
4144 "" | " "*) ;;
4145 *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
4146 esac],
4147 [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
4148 _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
4149fi
4150_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
4151 [Additional compiler flags for building library objects])
4152
4153#
4154# Check to make sure the static flag actually works.
4155#
4156wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
4157_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
4158 _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
4159 $lt_tmp_static_flag,
4160 [],
4161 [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
4162_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
4163 [Compiler flag to prevent dynamic linking])
4164])# _LT_COMPILER_PIC
4165
4166
4167# _LT_LINKER_SHLIBS([TAGNAME])
4168# ----------------------------
4169# See if the linker supports building shared libraries.
4170m4_defun([_LT_LINKER_SHLIBS],
4171[AC_REQUIRE([LT_PATH_LD])dnl
4172AC_REQUIRE([LT_PATH_NM])dnl
4173m4_require([_LT_FILEUTILS_DEFAULTS])dnl
4174m4_require([_LT_DECL_EGREP])dnl
4175m4_require([_LT_DECL_SED])dnl
4176m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
4177m4_require([_LT_TAG_COMPILER])dnl
4178AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
4179m4_if([$1], [CXX], [
4180 _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
4181 case $host_os in
4182 aix[[4-9]]*)
4183 # If we're using GNU nm, then we don't want the "-C" option.
4184 # -C means demangle to AIX nm, but means don't demangle with GNU nm
4185 if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
4186 _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
4187 else
4188 _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
4189 fi
4190 ;;
4191 pw32*)
4192 _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
4193 ;;
4194 cygwin* | mingw* | cegcc*)
4195 _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
4196 ;;
4197 linux* | k*bsd*-gnu)
4198 _LT_TAGVAR(link_all_deplibs, $1)=no
4199 ;;
4200 *)
4201 _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
4202 ;;
4203 esac
4204 _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
4205], [
4206 runpath_var=
4207 _LT_TAGVAR(allow_undefined_flag, $1)=
4208 _LT_TAGVAR(always_export_symbols, $1)=no
4209 _LT_TAGVAR(archive_cmds, $1)=
4210 _LT_TAGVAR(archive_expsym_cmds, $1)=
4211 _LT_TAGVAR(compiler_needs_object, $1)=no
4212 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
4213 _LT_TAGVAR(export_dynamic_flag_spec, $1)=
4214 _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
4215 _LT_TAGVAR(hardcode_automatic, $1)=no
4216 _LT_TAGVAR(hardcode_direct, $1)=no
4217 _LT_TAGVAR(hardcode_direct_absolute, $1)=no
4218 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
4219 _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
4220 _LT_TAGVAR(hardcode_libdir_separator, $1)=
4221 _LT_TAGVAR(hardcode_minus_L, $1)=no
4222 _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
4223 _LT_TAGVAR(inherit_rpath, $1)=no
4224 _LT_TAGVAR(link_all_deplibs, $1)=unknown
4225 _LT_TAGVAR(module_cmds, $1)=
4226 _LT_TAGVAR(module_expsym_cmds, $1)=
4227 _LT_TAGVAR(old_archive_from_new_cmds, $1)=
4228 _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
4229 _LT_TAGVAR(thread_safe_flag_spec, $1)=
4230 _LT_TAGVAR(whole_archive_flag_spec, $1)=
4231 # include_expsyms should be a list of space-separated symbols to be *always*
4232 # included in the symbol list
4233 _LT_TAGVAR(include_expsyms, $1)=
4234 # exclude_expsyms can be an extended regexp of symbols to exclude
4235 # it will be wrapped by ` (' and `)$', so one must not match beginning or
4236 # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
4237 # as well as any symbol that contains `d'.
4238 _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
4239 # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
4240 # platforms (ab)use it in PIC code, but their linkers get confused if
4241 # the symbol is explicitly referenced. Since portable code cannot
4242 # rely on this symbol name, it's probably fine to never include it in
4243 # preloaded symbol tables.
4244 # Exclude shared library initialization/finalization symbols.
4245dnl Note also adjust exclude_expsyms for C++ above.
4246 extract_expsyms_cmds=
4247
4248 case $host_os in
4249 cygwin* | mingw* | pw32* | cegcc*)
4250 # FIXME: the MSVC++ port hasn't been tested in a loooong time
4251 # When not using gcc, we currently assume that we are using
4252 # Microsoft Visual C++.
4253 if test "$GCC" != yes; then
4254 with_gnu_ld=no
4255 fi
4256 ;;
4257 interix*)
4258 # we just hope/assume this is gcc and not c89 (= MSVC++)
4259 with_gnu_ld=yes
4260 ;;
4261 openbsd*)
4262 with_gnu_ld=no
4263 ;;
4264 linux* | k*bsd*-gnu)
4265 _LT_TAGVAR(link_all_deplibs, $1)=no
4266 ;;
4267 esac
4268
4269 _LT_TAGVAR(ld_shlibs, $1)=yes
4270 if test "$with_gnu_ld" = yes; then
4271 # If archive_cmds runs LD, not CC, wlarc should be empty
4272 wlarc='${wl}'
4273
4274 # Set some defaults for GNU ld with shared library support. These
4275 # are reset later if shared libraries are not supported. Putting them
4276 # here allows them to be overridden if necessary.
4277 runpath_var=LD_RUN_PATH
4278 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
4279 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
4280 # ancient GNU ld didn't support --whole-archive et. al.
4281 if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
4282 _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
4283 else
4284 _LT_TAGVAR(whole_archive_flag_spec, $1)=
4285 fi
4286 supports_anon_versioning=no
4287 case `$LD -v 2>&1` in
4288 *GNU\ gold*) supports_anon_versioning=yes ;;
4289 *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
4290 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
4291 *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
4292 *\ 2.11.*) ;; # other 2.11 versions
4293 *) supports_anon_versioning=yes ;;
4294 esac
4295
4296 # See if GNU ld supports shared libraries.
4297 case $host_os in
4298 aix[[3-9]]*)
4299 # On AIX/PPC, the GNU linker is very broken
4300 if test "$host_cpu" != ia64; then
4301 _LT_TAGVAR(ld_shlibs, $1)=no
4302 cat <<_LT_EOF 1>&2
4303
4304*** Warning: the GNU linker, at least up to release 2.9.1, is reported
4305*** to be unable to reliably create shared libraries on AIX.
4306*** Therefore, libtool is disabling shared libraries support. If you
4307*** really care for shared libraries, you may want to modify your PATH
4308*** so that a non-GNU linker is found, and then restart.
4309
4310_LT_EOF
4311 fi
4312 ;;
4313
4314 amigaos*)
4315 case $host_cpu in
4316 powerpc)
4317 # see comment about AmigaOS4 .so support
4318 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4319 _LT_TAGVAR(archive_expsym_cmds, $1)=''
4320 ;;
4321 m68k)
4322 _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
4323 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
4324 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4325 ;;
4326 esac
4327 ;;
4328
4329 beos*)
4330 if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
4331 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
4332 # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
4333 # support --undefined. This deserves some investigation. FIXME
4334 _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4335 else
4336 _LT_TAGVAR(ld_shlibs, $1)=no
4337 fi
4338 ;;
4339
4340 cygwin* | mingw* | pw32* | cegcc*)
4341 # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
4342 # as there is no search path for DLLs.
4343 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
4344 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
4345 _LT_TAGVAR(always_export_symbols, $1)=no
4346 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
4347 _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
4348
4349 if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
4350 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
4351 # If the export-symbols file already is a .def file (1st line
4352 # is EXPORTS), use it as is; otherwise, prepend...
4353 _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
4354 cp $export_symbols $output_objdir/$soname.def;
4355 else
4356 echo EXPORTS > $output_objdir/$soname.def;
4357 cat $export_symbols >> $output_objdir/$soname.def;
4358 fi~
4359 $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
4360 else
4361 _LT_TAGVAR(ld_shlibs, $1)=no
4362 fi
4363 ;;
4364
4365 interix[[3-9]]*)
4366 _LT_TAGVAR(hardcode_direct, $1)=no
4367 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4368 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
4369 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
4370 # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
4371 # Instead, shared libraries are loaded at an image base (0x10000000 by
4372 # default) and relocated if they conflict, which is a slow very memory
4373 # consuming and fragmenting process. To avoid this, we pick a random,
4374 # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
4375 # time. Moving up from 0x10000000 also allows more sbrk(2) space.
4376 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
4377 _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
4378 ;;
4379
4380 gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
4381 tmp_diet=no
4382 if test "$host_os" = linux-dietlibc; then
4383 case $cc_basename in
4384 diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
4385 esac
4386 fi
4387 if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
4388 && test "$tmp_diet" = no
4389 then
4390 tmp_addflag=
4391 tmp_sharedflag='-shared'
4392 case $cc_basename,$host_cpu in
4393 pgcc*) # Portland Group C compiler
4394 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
4395 tmp_addflag=' $pic_flag'
4396 ;;
4397 pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
4398 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
4399 tmp_addflag=' $pic_flag -Mnomain' ;;
4400 ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
4401 tmp_addflag=' -i_dynamic' ;;
4402 efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
4403 tmp_addflag=' -i_dynamic -nofor_main' ;;
4404 ifc* | ifort*) # Intel Fortran compiler
4405 tmp_addflag=' -nofor_main' ;;
4406 lf95*) # Lahey Fortran 8.1
4407 _LT_TAGVAR(whole_archive_flag_spec, $1)=
4408 tmp_sharedflag='--shared' ;;
4409 xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
4410 tmp_sharedflag='-qmkshrobj'
4411 tmp_addflag= ;;
4412 esac
4413 case `$CC -V 2>&1 | sed 5q` in
4414 *Sun\ C*) # Sun C 5.9
4415 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
4416 _LT_TAGVAR(compiler_needs_object, $1)=yes
4417 tmp_sharedflag='-G' ;;
4418 *Sun\ F*) # Sun Fortran 8.3
4419 tmp_sharedflag='-G' ;;
4420 esac
4421 _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4422
4423 if test "x$supports_anon_versioning" = xyes; then
4424 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
4425 cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
4426 echo "local: *; };" >> $output_objdir/$libname.ver~
4427 $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
4428 fi
4429
4430 case $cc_basename in
4431 xlf*)
4432 # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
4433 _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
4434 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
4435 _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
4436 _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
4437 if test "x$supports_anon_versioning" = xyes; then
4438 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
4439 cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
4440 echo "local: *; };" >> $output_objdir/$libname.ver~
4441 $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
4442 fi
4443 ;;
4444 esac
4445 else
4446 _LT_TAGVAR(ld_shlibs, $1)=no
4447 fi
4448 ;;
4449
4450 netbsd* | netbsdelf*-gnu)
4451 if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
4452 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
4453 wlarc=
4454 else
4455 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4456 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
4457 fi
4458 ;;
4459
4460 solaris*)
4461 if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
4462 _LT_TAGVAR(ld_shlibs, $1)=no
4463 cat <<_LT_EOF 1>&2
4464
4465*** Warning: The releases 2.8.* of the GNU linker cannot reliably
4466*** create shared libraries on Solaris systems. Therefore, libtool
4467*** is disabling shared libraries support. We urge you to upgrade GNU
4468*** binutils to release 2.9.1 or newer. Another option is to modify
4469*** your PATH or compiler configuration so that the native linker is
4470*** used, and then restart.
4471
4472_LT_EOF
4473 elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
4474 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4475 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
4476 else
4477 _LT_TAGVAR(ld_shlibs, $1)=no
4478 fi
4479 ;;
4480
4481 sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
4482 case `$LD -v 2>&1` in
4483 *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
4484 _LT_TAGVAR(ld_shlibs, $1)=no
4485 cat <<_LT_EOF 1>&2
4486
4487*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
4488*** reliably create shared libraries on SCO systems. Therefore, libtool
4489*** is disabling shared libraries support. We urge you to upgrade GNU
4490*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
4491*** your PATH or compiler configuration so that the native linker is
4492*** used, and then restart.
4493
4494_LT_EOF
4495 ;;
4496 *)
4497 # For security reasons, it is highly recommended that you always
4498 # use absolute paths for naming shared libraries, and exclude the
4499 # DT_RUNPATH tag from executables and libraries. But doing so
4500 # requires that you compile everything twice, which is a pain.
4501 if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
4502 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
4503 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4504 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
4505 else
4506 _LT_TAGVAR(ld_shlibs, $1)=no
4507 fi
4508 ;;
4509 esac
4510 ;;
4511
4512 sunos4*)
4513 _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
4514 wlarc=
4515 _LT_TAGVAR(hardcode_direct, $1)=yes
4516 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4517 ;;
4518
4519 *)
4520 if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
4521 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4522 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
4523 else
4524 _LT_TAGVAR(ld_shlibs, $1)=no
4525 fi
4526 ;;
4527 esac
4528
4529 if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
4530 runpath_var=
4531 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
4532 _LT_TAGVAR(export_dynamic_flag_spec, $1)=
4533 _LT_TAGVAR(whole_archive_flag_spec, $1)=
4534 fi
4535 else
4536 # PORTME fill in a description of your system's linker (not GNU ld)
4537 case $host_os in
4538 aix3*)
4539 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
4540 _LT_TAGVAR(always_export_symbols, $1)=yes
4541 _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
4542 # Note: this linker hardcodes the directories in LIBPATH if there
4543 # are no directories specified by -L.
4544 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4545 if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
4546 # Neither direct hardcoding nor static linking is supported with a
4547 # broken collect2.
4548 _LT_TAGVAR(hardcode_direct, $1)=unsupported
4549 fi
4550 ;;
4551
4552 aix[[4-9]]*)
4553 if test "$host_cpu" = ia64; then
4554 # On IA64, the linker does run time linking by default, so we don't
4555 # have to do anything special.
4556 aix_use_runtimelinking=no
4557 exp_sym_flag='-Bexport'
4558 no_entry_flag=""
4559 else
4560 # If we're using GNU nm, then we don't want the "-C" option.
4561 # -C means demangle to AIX nm, but means don't demangle with GNU nm
4562 if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
4563 _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
4564 else
4565 _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
4566 fi
4567 aix_use_runtimelinking=no
4568
4569 # Test if we are trying to use run time linking or normal
4570 # AIX style linking. If -brtl is somewhere in LDFLAGS, we
4571 # need to do runtime linking.
4572 case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
4573 for ld_flag in $LDFLAGS; do
4574 if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
4575 aix_use_runtimelinking=yes
4576 break
4577 fi
4578 done
4579 ;;
4580 esac
4581
4582 exp_sym_flag='-bexport'
4583 no_entry_flag='-bnoentry'
4584 fi
4585
4586 # When large executables or shared objects are built, AIX ld can
4587 # have problems creating the table of contents. If linking a library
4588 # or program results in "error TOC overflow" add -mminimal-toc to
4589 # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
4590 # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
4591
4592 _LT_TAGVAR(archive_cmds, $1)=''
4593 _LT_TAGVAR(hardcode_direct, $1)=yes
4594 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
4595 _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
4596 _LT_TAGVAR(link_all_deplibs, $1)=yes
4597 _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
4598
4599 if test "$GCC" = yes; then
4600 case $host_os in aix4.[[012]]|aix4.[[012]].*)
4601 # We only want to do this on AIX 4.2 and lower, the check
4602 # below for broken collect2 doesn't work under 4.3+
4603 collect2name=`${CC} -print-prog-name=collect2`
4604 if test -f "$collect2name" &&
4605 strings "$collect2name" | $GREP resolve_lib_name >/dev/null
4606 then
4607 # We have reworked collect2
4608 :
4609 else
4610 # We have old collect2
4611 _LT_TAGVAR(hardcode_direct, $1)=unsupported
4612 # It fails to find uninstalled libraries when the uninstalled
4613 # path is not listed in the libpath. Setting hardcode_minus_L
4614 # to unsupported forces relinking
4615 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4616 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
4617 _LT_TAGVAR(hardcode_libdir_separator, $1)=
4618 fi
4619 ;;
4620 esac
4621 shared_flag='-shared'
4622 if test "$aix_use_runtimelinking" = yes; then
4623 shared_flag="$shared_flag "'${wl}-G'
4624 fi
4625 _LT_TAGVAR(link_all_deplibs, $1)=no
4626 else
4627 # not using gcc
4628 if test "$host_cpu" = ia64; then
4629 # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
4630 # chokes on -Wl,-G. The following line is correct:
4631 shared_flag='-G'
4632 else
4633 if test "$aix_use_runtimelinking" = yes; then
4634 shared_flag='${wl}-G'
4635 else
4636 shared_flag='${wl}-bM:SRE'
4637 fi
4638 fi
4639 fi
4640
4641 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
4642 # It seems that -bexpall does not export symbols beginning with
4643 # underscore (_), so it is better to generate a list of symbols to export.
4644 _LT_TAGVAR(always_export_symbols, $1)=yes
4645 if test "$aix_use_runtimelinking" = yes; then
4646 # Warning - without using the other runtime loading flags (-brtl),
4647 # -berok will link without error, but may produce a broken library.
4648 _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
4649 # Determine the default libpath from the value encoded in an
4650 # empty executable.
4651 _LT_SYS_MODULE_PATH_AIX
4652 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
4653 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
4654 else
4655 if test "$host_cpu" = ia64; then
4656 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
4657 _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
4658 _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
4659 else
4660 # Determine the default libpath from the value encoded in an
4661 # empty executable.
4662 _LT_SYS_MODULE_PATH_AIX
4663 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
4664 # Warning - without using the other run time loading flags,
4665 # -berok will link without error, but may produce a broken library.
4666 _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
4667 _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
4668 # Exported symbols can be pulled into shared objects from archives
4669 _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
4670 _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
4671 # This is similar to how AIX traditionally builds its shared libraries.
4672 _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
4673 fi
4674 fi
4675 ;;
4676
4677 amigaos*)
4678 case $host_cpu in
4679 powerpc)
4680 # see comment about AmigaOS4 .so support
4681 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
4682 _LT_TAGVAR(archive_expsym_cmds, $1)=''
4683 ;;
4684 m68k)
4685 _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
4686 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
4687 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4688 ;;
4689 esac
4690 ;;
4691
4692 bsdi[[45]]*)
4693 _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
4694 ;;
4695
4696 cygwin* | mingw* | pw32* | cegcc*)
4697 # When not using gcc, we currently assume that we are using
4698 # Microsoft Visual C++.
4699 # hardcode_libdir_flag_spec is actually meaningless, as there is
4700 # no search path for DLLs.
4701 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
4702 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
4703 # Tell ltmain to make .lib files, not .a files.
4704 libext=lib
4705 # Tell ltmain to make .dll files, not .so files.
4706 shrext_cmds=".dll"
4707 # FIXME: Setting linknames here is a bad hack.
4708 _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
4709 # The linker will automatically build a .lib file if we build a DLL.
4710 _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
4711 # FIXME: Should let the user specify the lib program.
4712 _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
4713 _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
4714 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
4715 ;;
4716
4717 darwin* | rhapsody*)
4718 _LT_DARWIN_LINKER_FEATURES($1)
4719 ;;
4720
4721 dgux*)
4722 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
4723 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
4724 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4725 ;;
4726
4727 freebsd1*)
4728 _LT_TAGVAR(ld_shlibs, $1)=no
4729 ;;
4730
4731 # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
4732 # support. Future versions do this automatically, but an explicit c++rt0.o
4733 # does not break anything, and helps significantly (at the cost of a little
4734 # extra space).
4735 freebsd2.2*)
4736 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
4737 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
4738 _LT_TAGVAR(hardcode_direct, $1)=yes
4739 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4740 ;;
4741
4742 # Unfortunately, older versions of FreeBSD 2 do not have this feature.
4743 freebsd2*)
4744 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
4745 _LT_TAGVAR(hardcode_direct, $1)=yes
4746 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4747 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4748 ;;
4749
4750 # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
4751 freebsd* | dragonfly*)
4752 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
4753 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
4754 _LT_TAGVAR(hardcode_direct, $1)=yes
4755 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4756 ;;
4757
4758 hpux9*)
4759 if test "$GCC" = yes; then
4760 _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
4761 else
4762 _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
4763 fi
4764 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
4765 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4766 _LT_TAGVAR(hardcode_direct, $1)=yes
4767
4768 # hardcode_minus_L: Not really in the search PATH,
4769 # but as the default location of the library.
4770 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4771 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
4772 ;;
4773
4774 hpux10*)
4775 if test "$GCC" = yes -a "$with_gnu_ld" = no; then
4776 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
4777 else
4778 _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
4779 fi
4780 if test "$with_gnu_ld" = no; then
4781 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
4782 _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
4783 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4784 _LT_TAGVAR(hardcode_direct, $1)=yes
4785 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
4786 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
4787 # hardcode_minus_L: Not really in the search PATH,
4788 # but as the default location of the library.
4789 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4790 fi
4791 ;;
4792
4793 hpux11*)
4794 if test "$GCC" = yes -a "$with_gnu_ld" = no; then
4795 case $host_cpu in
4796 hppa*64*)
4797 _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
4798 ;;
4799 ia64*)
4800 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
4801 ;;
4802 *)
4803 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
4804 ;;
4805 esac
4806 else
4807 case $host_cpu in
4808 hppa*64*)
4809 _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
4810 ;;
4811 ia64*)
4812 _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
4813 ;;
4814 *)
4815 _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
4816 ;;
4817 esac
4818 fi
4819 if test "$with_gnu_ld" = no; then
4820 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
4821 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4822
4823 case $host_cpu in
4824 hppa*64*|ia64*)
4825 _LT_TAGVAR(hardcode_direct, $1)=no
4826 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4827 ;;
4828 *)
4829 _LT_TAGVAR(hardcode_direct, $1)=yes
4830 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
4831 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
4832
4833 # hardcode_minus_L: Not really in the search PATH,
4834 # but as the default location of the library.
4835 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4836 ;;
4837 esac
4838 fi
4839 ;;
4840
4841 irix5* | irix6* | nonstopux*)
4842 if test "$GCC" = yes; then
4843 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
4844 # Try to use the -exported_symbol ld option, if it does not
4845 # work, assume that -exports_file does not work either and
4846 # implicitly export all symbols.
4847 save_LDFLAGS="$LDFLAGS"
4848 LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
4849 AC_LINK_IFELSE(int foo(void) {},
4850 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
4851 )
4852 LDFLAGS="$save_LDFLAGS"
4853 else
4854 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
4855 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
4856 fi
4857 _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
4858 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
4859 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4860 _LT_TAGVAR(inherit_rpath, $1)=yes
4861 _LT_TAGVAR(link_all_deplibs, $1)=yes
4862 ;;
4863
4864 netbsd* | netbsdelf*-gnu)
4865 if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
4866 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
4867 else
4868 _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
4869 fi
4870 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
4871 _LT_TAGVAR(hardcode_direct, $1)=yes
4872 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4873 ;;
4874
4875 newsos6)
4876 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
4877 _LT_TAGVAR(hardcode_direct, $1)=yes
4878 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
4879 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4880 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4881 ;;
4882
4883 *nto* | *qnx*)
4884 ;;
4885
4886 openbsd*)
4887 if test -f /usr/libexec/ld.so; then
4888 _LT_TAGVAR(hardcode_direct, $1)=yes
4889 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4890 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
4891 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
4892 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
4893 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
4894 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
4895 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
4896 else
4897 case $host_os in
4898 openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
4899 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
4900 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
4901 ;;
4902 *)
4903 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
4904 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
4905 ;;
4906 esac
4907 fi
4908 else
4909 _LT_TAGVAR(ld_shlibs, $1)=no
4910 fi
4911 ;;
4912
4913 os2*)
4914 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
4915 _LT_TAGVAR(hardcode_minus_L, $1)=yes
4916 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
4917 _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
4918 _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
4919 ;;
4920
4921 osf3*)
4922 if test "$GCC" = yes; then
4923 _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
4924 _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
4925 else
4926 _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
4927 _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
4928 fi
4929 _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
4930 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
4931 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4932 ;;
4933
4934 osf4* | osf5*) # as osf3* with the addition of -msym flag
4935 if test "$GCC" = yes; then
4936 _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
4937 _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
4938 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
4939 else
4940 _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
4941 _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
4942 _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
4943 $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
4944
4945 # Both c and cxx compiler support -rpath directly
4946 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
4947 fi
4948 _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
4949 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
4950 ;;
4951
4952 solaris*)
4953 _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
4954 if test "$GCC" = yes; then
4955 wlarc='${wl}'
4956 _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
4957 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
4958 $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
4959 else
4960 case `$CC -V 2>&1` in
4961 *"Compilers 5.0"*)
4962 wlarc=''
4963 _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
4964 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
4965 $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
4966 ;;
4967 *)
4968 wlarc='${wl}'
4969 _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
4970 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
4971 $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
4972 ;;
4973 esac
4974 fi
4975 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
4976 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
4977 case $host_os in
4978 solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
4979 *)
4980 # The compiler driver will combine and reorder linker options,
4981 # but understands `-z linker_flag'. GCC discards it without `$wl',
4982 # but is careful enough not to reorder.
4983 # Supported since Solaris 2.6 (maybe 2.5.1?)
4984 if test "$GCC" = yes; then
4985 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
4986 else
4987 _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
4988 fi
4989 ;;
4990 esac
4991 _LT_TAGVAR(link_all_deplibs, $1)=yes
4992 ;;
4993
4994 sunos4*)
4995 if test "x$host_vendor" = xsequent; then
4996 # Use $CC to link under sequent, because it throws in some extra .o
4997 # files that make .init and .fini sections work.
4998 _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
4999 else
5000 _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
5001 fi
5002 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
5003 _LT_TAGVAR(hardcode_direct, $1)=yes
5004 _LT_TAGVAR(hardcode_minus_L, $1)=yes
5005 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5006 ;;
5007
5008 sysv4)
5009 case $host_vendor in
5010 sni)
5011 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
5012 _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
5013 ;;
5014 siemens)
5015 ## LD is ld it makes a PLAMLIB
5016 ## CC just makes a GrossModule.
5017 _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
5018 _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
5019 _LT_TAGVAR(hardcode_direct, $1)=no
5020 ;;
5021 motorola)
5022 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
5023 _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
5024 ;;
5025 esac
5026 runpath_var='LD_RUN_PATH'
5027 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5028 ;;
5029
5030 sysv4.3*)
5031 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
5032 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5033 _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
5034 ;;
5035
5036 sysv4*MP*)
5037 if test -d /usr/nec; then
5038 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
5039 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5040 runpath_var=LD_RUN_PATH
5041 hardcode_runpath_var=yes
5042 _LT_TAGVAR(ld_shlibs, $1)=yes
5043 fi
5044 ;;
5045
5046 sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
5047 _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
5048 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
5049 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5050 runpath_var='LD_RUN_PATH'
5051
5052 if test "$GCC" = yes; then
5053 _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5054 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5055 else
5056 _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5057 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5058 fi
5059 ;;
5060
5061 sysv5* | sco3.2v5* | sco5v6*)
5062 # Note: We can NOT use -z defs as we might desire, because we do not
5063 # link with -lc, and that would cause any symbols used from libc to
5064 # always be unresolved, which means just about no library would
5065 # ever link correctly. If we're not using GNU ld we use -z text
5066 # though, which does catch some bad symbols but isn't as heavy-handed
5067 # as -z defs.
5068 _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
5069 _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
5070 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
5071 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5072 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
5073 _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
5074 _LT_TAGVAR(link_all_deplibs, $1)=yes
5075 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
5076 runpath_var='LD_RUN_PATH'
5077
5078 if test "$GCC" = yes; then
5079 _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5080 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5081 else
5082 _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5083 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
5084 fi
5085 ;;
5086
5087 uts4*)
5088 _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
5089 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
5090 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5091 ;;
5092
5093 *)
5094 _LT_TAGVAR(ld_shlibs, $1)=no
5095 ;;
5096 esac
5097
5098 if test x$host_vendor = xsni; then
5099 case $host in
5100 sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
5101 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
5102 ;;
5103 esac
5104 fi
5105 fi
5106])
5107AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
5108test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
5109
5110_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
5111
5112_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
5113_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
5114_LT_DECL([], [extract_expsyms_cmds], [2],
5115 [The commands to extract the exported symbol list from a shared archive])
5116
5117#
5118# Do we need to explicitly link libc?
5119#
5120case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
5121x|xyes)
5122 # Assume -lc should be added
5123 _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
5124
5125 if test "$enable_shared" = yes && test "$GCC" = yes; then
5126 case $_LT_TAGVAR(archive_cmds, $1) in
5127 *'~'*)
5128 # FIXME: we may have to deal with multi-command sequences.
5129 ;;
5130 '$CC '*)
5131 # Test whether the compiler implicitly links with -lc since on some
5132 # systems, -lgcc has to come before -lc. If gcc already passes -lc
5133 # to ld, don't add -lc before -lgcc.
5134 AC_MSG_CHECKING([whether -lc should be explicitly linked in])
5135 $RM conftest*
5136 echo "$lt_simple_compile_test_code" > conftest.$ac_ext
5137
5138 if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
5139 soname=conftest
5140 lib=conftest
5141 libobjs=conftest.$ac_objext
5142 deplibs=
5143 wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
5144 pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
5145 compiler_flags=-v
5146 linker_flags=-v
5147 verstring=
5148 output_objdir=.
5149 libname=conftest
5150 lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
5151 _LT_TAGVAR(allow_undefined_flag, $1)=
5152 if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
5153 then
5154 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
5155 else
5156 _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
5157 fi
5158 _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
5159 else
5160 cat conftest.err 1>&5
5161 fi
5162 $RM conftest*
5163 AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
5164 ;;
5165 esac
5166 fi
5167 ;;
5168esac
5169
5170_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
5171 [Whether or not to add -lc for building shared libraries])
5172_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
5173 [enable_shared_with_static_runtimes], [0],
5174 [Whether or not to disallow shared libs when runtime libs are static])
5175_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
5176 [Compiler flag to allow reflexive dlopens])
5177_LT_TAGDECL([], [whole_archive_flag_spec], [1],
5178 [Compiler flag to generate shared objects directly from archives])
5179_LT_TAGDECL([], [compiler_needs_object], [1],
5180 [Whether the compiler copes with passing no objects directly])
5181_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
5182 [Create an old-style archive from a shared archive])
5183_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
5184 [Create a temporary old-style archive to link instead of a shared archive])
5185_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
5186_LT_TAGDECL([], [archive_expsym_cmds], [2])
5187_LT_TAGDECL([], [module_cmds], [2],
5188 [Commands used to build a loadable module if different from building
5189 a shared archive.])
5190_LT_TAGDECL([], [module_expsym_cmds], [2])
5191_LT_TAGDECL([], [with_gnu_ld], [1],
5192 [Whether we are building with GNU ld or not])
5193_LT_TAGDECL([], [allow_undefined_flag], [1],
5194 [Flag that allows shared libraries with undefined symbols to be built])
5195_LT_TAGDECL([], [no_undefined_flag], [1],
5196 [Flag that enforces no undefined symbols])
5197_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
5198 [Flag to hardcode $libdir into a binary during linking.
5199 This must work even if $libdir does not exist])
5200_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
5201 [[If ld is used when linking, flag to hardcode $libdir into a binary
5202 during linking. This must work even if $libdir does not exist]])
5203_LT_TAGDECL([], [hardcode_libdir_separator], [1],
5204 [Whether we need a single "-rpath" flag with a separated argument])
5205_LT_TAGDECL([], [hardcode_direct], [0],
5206 [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
5207 DIR into the resulting binary])
5208_LT_TAGDECL([], [hardcode_direct_absolute], [0],
5209 [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
5210 DIR into the resulting binary and the resulting library dependency is
5211 "absolute", i.e impossible to change by setting ${shlibpath_var} if the
5212 library is relocated])
5213_LT_TAGDECL([], [hardcode_minus_L], [0],
5214 [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
5215 into the resulting binary])
5216_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
5217 [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
5218 into the resulting binary])
5219_LT_TAGDECL([], [hardcode_automatic], [0],
5220 [Set to "yes" if building a shared library automatically hardcodes DIR
5221 into the library and all subsequent libraries and executables linked
5222 against it])
5223_LT_TAGDECL([], [inherit_rpath], [0],
5224 [Set to yes if linker adds runtime paths of dependent libraries
5225 to runtime path list])
5226_LT_TAGDECL([], [link_all_deplibs], [0],
5227 [Whether libtool must link a program against all its dependency libraries])
5228_LT_TAGDECL([], [fix_srcfile_path], [1],
5229 [Fix the shell variable $srcfile for the compiler])
5230_LT_TAGDECL([], [always_export_symbols], [0],
5231 [Set to "yes" if exported symbols are required])
5232_LT_TAGDECL([], [export_symbols_cmds], [2],
5233 [The commands to list exported symbols])
5234_LT_TAGDECL([], [exclude_expsyms], [1],
5235 [Symbols that should not be listed in the preloaded symbols])
5236_LT_TAGDECL([], [include_expsyms], [1],
5237 [Symbols that must always be exported])
5238_LT_TAGDECL([], [prelink_cmds], [2],
5239 [Commands necessary for linking programs (against libraries) with templates])
5240_LT_TAGDECL([], [file_list_spec], [1],
5241 [Specify filename containing input files])
5242dnl FIXME: Not yet implemented
5243dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
5244dnl [Compiler flag to generate thread safe objects])
5245])# _LT_LINKER_SHLIBS
5246
5247
5248# _LT_LANG_C_CONFIG([TAG])
5249# ------------------------
5250# Ensure that the configuration variables for a C compiler are suitably
5251# defined. These variables are subsequently used by _LT_CONFIG to write
5252# the compiler configuration to `libtool'.
5253m4_defun([_LT_LANG_C_CONFIG],
5254[m4_require([_LT_DECL_EGREP])dnl
5255lt_save_CC="$CC"
5256AC_LANG_PUSH(C)
5257
5258# Source file extension for C test sources.
5259ac_ext=c
5260
5261# Object file extension for compiled C test sources.
5262objext=o
5263_LT_TAGVAR(objext, $1)=$objext
5264
5265# Code to be used in simple compile tests
5266lt_simple_compile_test_code="int some_variable = 0;"
5267
5268# Code to be used in simple link tests
5269lt_simple_link_test_code='int main(){return(0);}'
5270
5271_LT_TAG_COMPILER
5272# Save the default compiler, since it gets overwritten when the other
5273# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
5274compiler_DEFAULT=$CC
5275
5276# save warnings/boilerplate of simple test code
5277_LT_COMPILER_BOILERPLATE
5278_LT_LINKER_BOILERPLATE
5279
5280## CAVEAT EMPTOR:
5281## There is no encapsulation within the following macros, do not change
5282## the running order or otherwise move them around unless you know exactly
5283## what you are doing...
5284if test -n "$compiler"; then
5285 _LT_COMPILER_NO_RTTI($1)
5286 _LT_COMPILER_PIC($1)
5287 _LT_COMPILER_C_O($1)
5288 _LT_COMPILER_FILE_LOCKS($1)
5289 _LT_LINKER_SHLIBS($1)
5290 _LT_SYS_DYNAMIC_LINKER($1)
5291 _LT_LINKER_HARDCODE_LIBPATH($1)
5292 LT_SYS_DLOPEN_SELF
5293 _LT_CMD_STRIPLIB
5294
5295 # Report which library types will actually be built
5296 AC_MSG_CHECKING([if libtool supports shared libraries])
5297 AC_MSG_RESULT([$can_build_shared])
5298
5299 AC_MSG_CHECKING([whether to build shared libraries])
5300 test "$can_build_shared" = "no" && enable_shared=no
5301
5302 # On AIX, shared libraries and static libraries use the same namespace, and
5303 # are all built from PIC.
5304 case $host_os in
5305 aix3*)
5306 test "$enable_shared" = yes && enable_static=no
5307 if test -n "$RANLIB"; then
5308 archive_cmds="$archive_cmds~\$RANLIB \$lib"
5309 postinstall_cmds='$RANLIB $lib'
5310 fi
5311 ;;
5312
5313 aix[[4-9]]*)
5314 if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
5315 test "$enable_shared" = yes && enable_static=no
5316 fi
5317 ;;
5318 esac
5319 AC_MSG_RESULT([$enable_shared])
5320
5321 AC_MSG_CHECKING([whether to build static libraries])
5322 # Make sure either enable_shared or enable_static is yes.
5323 test "$enable_shared" = yes || enable_static=yes
5324 AC_MSG_RESULT([$enable_static])
5325
5326 _LT_CONFIG($1)
5327fi
5328AC_LANG_POP
5329CC="$lt_save_CC"
5330])# _LT_LANG_C_CONFIG
5331
5332
5333# _LT_PROG_CXX
5334# ------------
5335# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
5336# compiler, we have our own version here.
5337m4_defun([_LT_PROG_CXX],
5338[
5339pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
5340AC_PROG_CXX
5341if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
5342 ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
5343 (test "X$CXX" != "Xg++"))) ; then
5344 AC_PROG_CXXCPP
5345else
5346 _lt_caught_CXX_error=yes
5347fi
5348popdef([AC_MSG_ERROR])
5349])# _LT_PROG_CXX
5350
5351dnl aclocal-1.4 backwards compatibility:
5352dnl AC_DEFUN([_LT_PROG_CXX], [])
5353
5354
5355# _LT_LANG_CXX_CONFIG([TAG])
5356# --------------------------
5357# Ensure that the configuration variables for a C++ compiler are suitably
5358# defined. These variables are subsequently used by _LT_CONFIG to write
5359# the compiler configuration to `libtool'.
5360m4_defun([_LT_LANG_CXX_CONFIG],
5361[AC_REQUIRE([_LT_PROG_CXX])dnl
5362m4_require([_LT_FILEUTILS_DEFAULTS])dnl
5363m4_require([_LT_DECL_EGREP])dnl
5364
5365AC_LANG_PUSH(C++)
5366_LT_TAGVAR(archive_cmds_need_lc, $1)=no
5367_LT_TAGVAR(allow_undefined_flag, $1)=
5368_LT_TAGVAR(always_export_symbols, $1)=no
5369_LT_TAGVAR(archive_expsym_cmds, $1)=
5370_LT_TAGVAR(compiler_needs_object, $1)=no
5371_LT_TAGVAR(export_dynamic_flag_spec, $1)=
5372_LT_TAGVAR(hardcode_direct, $1)=no
5373_LT_TAGVAR(hardcode_direct_absolute, $1)=no
5374_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
5375_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
5376_LT_TAGVAR(hardcode_libdir_separator, $1)=
5377_LT_TAGVAR(hardcode_minus_L, $1)=no
5378_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
5379_LT_TAGVAR(hardcode_automatic, $1)=no
5380_LT_TAGVAR(inherit_rpath, $1)=no
5381_LT_TAGVAR(module_cmds, $1)=
5382_LT_TAGVAR(module_expsym_cmds, $1)=
5383_LT_TAGVAR(link_all_deplibs, $1)=unknown
5384_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
5385_LT_TAGVAR(no_undefined_flag, $1)=
5386_LT_TAGVAR(whole_archive_flag_spec, $1)=
5387_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
5388
5389# Source file extension for C++ test sources.
5390ac_ext=cpp
5391
5392# Object file extension for compiled C++ test sources.
5393objext=o
5394_LT_TAGVAR(objext, $1)=$objext
5395
5396# No sense in running all these tests if we already determined that
5397# the CXX compiler isn't working. Some variables (like enable_shared)
5398# are currently assumed to apply to all compilers on this platform,
5399# and will be corrupted by setting them based on a non-working compiler.
5400if test "$_lt_caught_CXX_error" != yes; then
5401 # Code to be used in simple compile tests
5402 lt_simple_compile_test_code="int some_variable = 0;"
5403
5404 # Code to be used in simple link tests
5405 lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
5406
5407 # ltmain only uses $CC for tagged configurations so make sure $CC is set.
5408 _LT_TAG_COMPILER
5409
5410 # save warnings/boilerplate of simple test code
5411 _LT_COMPILER_BOILERPLATE
5412 _LT_LINKER_BOILERPLATE
5413
5414 # Allow CC to be a program name with arguments.
5415 lt_save_CC=$CC
5416 lt_save_LD=$LD
5417 lt_save_GCC=$GCC
5418 GCC=$GXX
5419 lt_save_with_gnu_ld=$with_gnu_ld
5420 lt_save_path_LD=$lt_cv_path_LD
5421 if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
5422 lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
5423 else
5424 $as_unset lt_cv_prog_gnu_ld
5425 fi
5426 if test -n "${lt_cv_path_LDCXX+set}"; then
5427 lt_cv_path_LD=$lt_cv_path_LDCXX
5428 else
5429 $as_unset lt_cv_path_LD
5430 fi
5431 test -z "${LDCXX+set}" || LD=$LDCXX
5432 CC=${CXX-"c++"}
5433 compiler=$CC
5434 _LT_TAGVAR(compiler, $1)=$CC
5435 _LT_CC_BASENAME([$compiler])
5436
5437 if test -n "$compiler"; then
5438 # We don't want -fno-exception when compiling C++ code, so set the
5439 # no_builtin_flag separately
5440 if test "$GXX" = yes; then
5441 _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
5442 else
5443 _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
5444 fi
5445
5446 if test "$GXX" = yes; then
5447 # Set up default GNU C++ configuration
5448
5449 LT_PATH_LD
5450
5451 # Check if GNU C++ uses GNU ld as the underlying linker, since the
5452 # archiving commands below assume that GNU ld is being used.
5453 if test "$with_gnu_ld" = yes; then
5454 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
5455 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
5456
5457 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
5458 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
5459
5460 # If archive_cmds runs LD, not CC, wlarc should be empty
5461 # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
5462 # investigate it a little bit more. (MM)
5463 wlarc='${wl}'
5464
5465 # ancient GNU ld didn't support --whole-archive et. al.
5466 if eval "`$CC -print-prog-name=ld` --help 2>&1" |
5467 $GREP 'no-whole-archive' > /dev/null; then
5468 _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
5469 else
5470 _LT_TAGVAR(whole_archive_flag_spec, $1)=
5471 fi
5472 else
5473 with_gnu_ld=no
5474 wlarc=
5475
5476 # A generic and very simple default shared library creation
5477 # command for GNU C++ for the case where it uses the native
5478 # linker, instead of GNU ld. If possible, this setting should
5479 # overridden to take advantage of the native linker features on
5480 # the platform it is being used on.
5481 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
5482 fi
5483
5484 # Commands to make compiler produce verbose output that lists
5485 # what "hidden" libraries, object files and flags are used when
5486 # linking a shared library.
5487 output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
5488
5489 else
5490 GXX=no
5491 with_gnu_ld=no
5492 wlarc=
5493 fi
5494
5495 # PORTME: fill in a description of your system's C++ link characteristics
5496 AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
5497 _LT_TAGVAR(ld_shlibs, $1)=yes
5498 case $host_os in
5499 aix3*)
5500 # FIXME: insert proper C++ library support
5501 _LT_TAGVAR(ld_shlibs, $1)=no
5502 ;;
5503 aix[[4-9]]*)
5504 if test "$host_cpu" = ia64; then
5505 # On IA64, the linker does run time linking by default, so we don't
5506 # have to do anything special.
5507 aix_use_runtimelinking=no
5508 exp_sym_flag='-Bexport'
5509 no_entry_flag=""
5510 else
5511 aix_use_runtimelinking=no
5512
5513 # Test if we are trying to use run time linking or normal
5514 # AIX style linking. If -brtl is somewhere in LDFLAGS, we
5515 # need to do runtime linking.
5516 case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
5517 for ld_flag in $LDFLAGS; do
5518 case $ld_flag in
5519 *-brtl*)
5520 aix_use_runtimelinking=yes
5521 break
5522 ;;
5523 esac
5524 done
5525 ;;
5526 esac
5527
5528 exp_sym_flag='-bexport'
5529 no_entry_flag='-bnoentry'
5530 fi
5531
5532 # When large executables or shared objects are built, AIX ld can
5533 # have problems creating the table of contents. If linking a library
5534 # or program results in "error TOC overflow" add -mminimal-toc to
5535 # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
5536 # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
5537
5538 _LT_TAGVAR(archive_cmds, $1)=''
5539 _LT_TAGVAR(hardcode_direct, $1)=yes
5540 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
5541 _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
5542 _LT_TAGVAR(link_all_deplibs, $1)=yes
5543 _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
5544
5545 if test "$GXX" = yes; then
5546 case $host_os in aix4.[[012]]|aix4.[[012]].*)
5547 # We only want to do this on AIX 4.2 and lower, the check
5548 # below for broken collect2 doesn't work under 4.3+
5549 collect2name=`${CC} -print-prog-name=collect2`
5550 if test -f "$collect2name" &&
5551 strings "$collect2name" | $GREP resolve_lib_name >/dev/null
5552 then
5553 # We have reworked collect2
5554 :
5555 else
5556 # We have old collect2
5557 _LT_TAGVAR(hardcode_direct, $1)=unsupported
5558 # It fails to find uninstalled libraries when the uninstalled
5559 # path is not listed in the libpath. Setting hardcode_minus_L
5560 # to unsupported forces relinking
5561 _LT_TAGVAR(hardcode_minus_L, $1)=yes
5562 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
5563 _LT_TAGVAR(hardcode_libdir_separator, $1)=
5564 fi
5565 esac
5566 shared_flag='-shared'
5567 if test "$aix_use_runtimelinking" = yes; then
5568 shared_flag="$shared_flag "'${wl}-G'
5569 fi
5570 else
5571 # not using gcc
5572 if test "$host_cpu" = ia64; then
5573 # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
5574 # chokes on -Wl,-G. The following line is correct:
5575 shared_flag='-G'
5576 else
5577 if test "$aix_use_runtimelinking" = yes; then
5578 shared_flag='${wl}-G'
5579 else
5580 shared_flag='${wl}-bM:SRE'
5581 fi
5582 fi
5583 fi
5584
5585 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
5586 # It seems that -bexpall does not export symbols beginning with
5587 # underscore (_), so it is better to generate a list of symbols to
5588 # export.
5589 _LT_TAGVAR(always_export_symbols, $1)=yes
5590 if test "$aix_use_runtimelinking" = yes; then
5591 # Warning - without using the other runtime loading flags (-brtl),
5592 # -berok will link without error, but may produce a broken library.
5593 _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
5594 # Determine the default libpath from the value encoded in an empty
5595 # executable.
5596 _LT_SYS_MODULE_PATH_AIX
5597 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
5598
5599 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
5600 else
5601 if test "$host_cpu" = ia64; then
5602 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
5603 _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
5604 _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
5605 else
5606 # Determine the default libpath from the value encoded in an
5607 # empty executable.
5608 _LT_SYS_MODULE_PATH_AIX
5609 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
5610 # Warning - without using the other run time loading flags,
5611 # -berok will link without error, but may produce a broken library.
5612 _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
5613 _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
5614 # Exported symbols can be pulled into shared objects from archives
5615 _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
5616 _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
5617 # This is similar to how AIX traditionally builds its shared
5618 # libraries.
5619 _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
5620 fi
5621 fi
5622 ;;
5623
5624 beos*)
5625 if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
5626 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
5627 # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
5628 # support --undefined. This deserves some investigation. FIXME
5629 _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
5630 else
5631 _LT_TAGVAR(ld_shlibs, $1)=no
5632 fi
5633 ;;
5634
5635 chorus*)
5636 case $cc_basename in
5637 *)
5638 # FIXME: insert proper C++ library support
5639 _LT_TAGVAR(ld_shlibs, $1)=no
5640 ;;
5641 esac
5642 ;;
5643
5644 cygwin* | mingw* | pw32* | cegcc*)
5645 # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
5646 # as there is no search path for DLLs.
5647 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
5648 _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
5649 _LT_TAGVAR(always_export_symbols, $1)=no
5650 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
5651
5652 if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
5653 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
5654 # If the export-symbols file already is a .def file (1st line
5655 # is EXPORTS), use it as is; otherwise, prepend...
5656 _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
5657 cp $export_symbols $output_objdir/$soname.def;
5658 else
5659 echo EXPORTS > $output_objdir/$soname.def;
5660 cat $export_symbols >> $output_objdir/$soname.def;
5661 fi~
5662 $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
5663 else
5664 _LT_TAGVAR(ld_shlibs, $1)=no
5665 fi
5666 ;;
5667 darwin* | rhapsody*)
5668 _LT_DARWIN_LINKER_FEATURES($1)
5669 ;;
5670
5671 dgux*)
5672 case $cc_basename in
5673 ec++*)
5674 # FIXME: insert proper C++ library support
5675 _LT_TAGVAR(ld_shlibs, $1)=no
5676 ;;
5677 ghcx*)
5678 # Green Hills C++ Compiler
5679 # FIXME: insert proper C++ library support
5680 _LT_TAGVAR(ld_shlibs, $1)=no
5681 ;;
5682 *)
5683 # FIXME: insert proper C++ library support
5684 _LT_TAGVAR(ld_shlibs, $1)=no
5685 ;;
5686 esac
5687 ;;
5688
5689 freebsd[[12]]*)
5690 # C++ shared libraries reported to be fairly broken before
5691 # switch to ELF
5692 _LT_TAGVAR(ld_shlibs, $1)=no
5693 ;;
5694
5695 freebsd-elf*)
5696 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
5697 ;;
5698
5699 freebsd* | dragonfly*)
5700 # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
5701 # conventions
5702 _LT_TAGVAR(ld_shlibs, $1)=yes
5703 ;;
5704
5705 gnu*)
5706 ;;
5707
5708 hpux9*)
5709 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
5710 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
5711 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
5712 _LT_TAGVAR(hardcode_direct, $1)=yes
5713 _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
5714 # but as the default
5715 # location of the library.
5716
5717 case $cc_basename in
5718 CC*)
5719 # FIXME: insert proper C++ library support
5720 _LT_TAGVAR(ld_shlibs, $1)=no
5721 ;;
5722 aCC*)
5723 _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
5724 # Commands to make compiler produce verbose output that lists
5725 # what "hidden" libraries, object files and flags are used when
5726 # linking a shared library.
5727 #
5728 # There doesn't appear to be a way to prevent this compiler from
5729 # explicitly linking system object files so we need to strip them
5730 # from the output so that they don't get included in the library
5731 # dependencies.
5732 output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
5733 ;;
5734 *)
5735 if test "$GXX" = yes; then
5736 _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
5737 else
5738 # FIXME: insert proper C++ library support
5739 _LT_TAGVAR(ld_shlibs, $1)=no
5740 fi
5741 ;;
5742 esac
5743 ;;
5744
5745 hpux10*|hpux11*)
5746 if test $with_gnu_ld = no; then
5747 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
5748 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
5749
5750 case $host_cpu in
5751 hppa*64*|ia64*)
5752 ;;
5753 *)
5754 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
5755 ;;
5756 esac
5757 fi
5758 case $host_cpu in
5759 hppa*64*|ia64*)
5760 _LT_TAGVAR(hardcode_direct, $1)=no
5761 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5762 ;;
5763 *)
5764 _LT_TAGVAR(hardcode_direct, $1)=yes
5765 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
5766 _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
5767 # but as the default
5768 # location of the library.
5769 ;;
5770 esac
5771
5772 case $cc_basename in
5773 CC*)
5774 # FIXME: insert proper C++ library support
5775 _LT_TAGVAR(ld_shlibs, $1)=no
5776 ;;
5777 aCC*)
5778 case $host_cpu in
5779 hppa*64*)
5780 _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5781 ;;
5782 ia64*)
5783 _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5784 ;;
5785 *)
5786 _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5787 ;;
5788 esac
5789 # Commands to make compiler produce verbose output that lists
5790 # what "hidden" libraries, object files and flags are used when
5791 # linking a shared library.
5792 #
5793 # There doesn't appear to be a way to prevent this compiler from
5794 # explicitly linking system object files so we need to strip them
5795 # from the output so that they don't get included in the library
5796 # dependencies.
5797 output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
5798 ;;
5799 *)
5800 if test "$GXX" = yes; then
5801 if test $with_gnu_ld = no; then
5802 case $host_cpu in
5803 hppa*64*)
5804 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5805 ;;
5806 ia64*)
5807 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5808 ;;
5809 *)
5810 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5811 ;;
5812 esac
5813 fi
5814 else
5815 # FIXME: insert proper C++ library support
5816 _LT_TAGVAR(ld_shlibs, $1)=no
5817 fi
5818 ;;
5819 esac
5820 ;;
5821
5822 interix[[3-9]]*)
5823 _LT_TAGVAR(hardcode_direct, $1)=no
5824 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
5825 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
5826 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
5827 # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
5828 # Instead, shared libraries are loaded at an image base (0x10000000 by
5829 # default) and relocated if they conflict, which is a slow very memory
5830 # consuming and fragmenting process. To avoid this, we pick a random,
5831 # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
5832 # time. Moving up from 0x10000000 also allows more sbrk(2) space.
5833 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
5834 _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
5835 ;;
5836 irix5* | irix6*)
5837 case $cc_basename in
5838 CC*)
5839 # SGI C++
5840 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
5841
5842 # Archives containing C++ object files must be created using
5843 # "CC -ar", where "CC" is the IRIX C++ compiler. This is
5844 # necessary to make sure instantiated templates are included
5845 # in the archive.
5846 _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
5847 ;;
5848 *)
5849 if test "$GXX" = yes; then
5850 if test "$with_gnu_ld" = no; then
5851 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
5852 else
5853 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
5854 fi
5855 fi
5856 _LT_TAGVAR(link_all_deplibs, $1)=yes
5857 ;;
5858 esac
5859 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
5860 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
5861 _LT_TAGVAR(inherit_rpath, $1)=yes
5862 ;;
5863
5864 linux* | k*bsd*-gnu | kopensolaris*-gnu)
5865 case $cc_basename in
5866 KCC*)
5867 # Kuck and Associates, Inc. (KAI) C++ Compiler
5868
5869 # KCC will only create a shared library if the output file
5870 # ends with ".so" (or ".sl" for HP-UX), so rename the library
5871 # to its proper name (with version) after linking.
5872 _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
5873 _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
5874 # Commands to make compiler produce verbose output that lists
5875 # what "hidden" libraries, object files and flags are used when
5876 # linking a shared library.
5877 #
5878 # There doesn't appear to be a way to prevent this compiler from
5879 # explicitly linking system object files so we need to strip them
5880 # from the output so that they don't get included in the library
5881 # dependencies.
5882 output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
5883
5884 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
5885 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
5886
5887 # Archives containing C++ object files must be created using
5888 # "CC -Bstatic", where "CC" is the KAI C++ compiler.
5889 _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
5890 ;;
5891 icpc* | ecpc* )
5892 # Intel C++
5893 with_gnu_ld=yes
5894 # version 8.0 and above of icpc choke on multiply defined symbols
5895 # if we add $predep_objects and $postdep_objects, however 7.1 and
5896 # earlier do not add the objects themselves.
5897 case `$CC -V 2>&1` in
5898 *"Version 7."*)
5899 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
5900 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
5901 ;;
5902 *) # Version 8.0 or newer
5903 tmp_idyn=
5904 case $host_cpu in
5905 ia64*) tmp_idyn=' -i_dynamic';;
5906 esac
5907 _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
5908 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
5909 ;;
5910 esac
5911 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
5912 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
5913 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
5914 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
5915 ;;
5916 pgCC* | pgcpp*)
5917 # Portland Group C++ compiler
5918 case `$CC -V` in
5919 *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
5920 _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
5921 rm -rf $tpldir~
5922 $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
5923 compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
5924 _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
5925 rm -rf $tpldir~
5926 $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
5927 $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
5928 $RANLIB $oldlib'
5929 _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
5930 rm -rf $tpldir~
5931 $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
5932 $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
5933 _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
5934 rm -rf $tpldir~
5935 $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
5936 $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
5937 ;;
5938 *) # Version 6 will use weak symbols
5939 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
5940 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
5941 ;;
5942 esac
5943
5944 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
5945 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
5946 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
5947 ;;
5948 cxx*)
5949 # Compaq C++
5950 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
5951 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
5952
5953 runpath_var=LD_RUN_PATH
5954 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
5955 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
5956
5957 # Commands to make compiler produce verbose output that lists
5958 # what "hidden" libraries, object files and flags are used when
5959 # linking a shared library.
5960 #
5961 # There doesn't appear to be a way to prevent this compiler from
5962 # explicitly linking system object files so we need to strip them
5963 # from the output so that they don't get included in the library
5964 # dependencies.
5965 output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
5966 ;;
5967 xl*)
5968 # IBM XL 8.0 on PPC, with GNU ld
5969 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
5970 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
5971 _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
5972 if test "x$supports_anon_versioning" = xyes; then
5973 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
5974 cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
5975 echo "local: *; };" >> $output_objdir/$libname.ver~
5976 $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
5977 fi
5978 ;;
5979 *)
5980 case `$CC -V 2>&1 | sed 5q` in
5981 *Sun\ C*)
5982 # Sun C++ 5.9
5983 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
5984 _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
5985 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
5986 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
5987 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
5988 _LT_TAGVAR(compiler_needs_object, $1)=yes
5989
5990 # Not sure whether something based on
5991 # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
5992 # would be better.
5993 output_verbose_link_cmd='echo'
5994
5995 # Archives containing C++ object files must be created using
5996 # "CC -xar", where "CC" is the Sun C++ compiler. This is
5997 # necessary to make sure instantiated templates are included
5998 # in the archive.
5999 _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
6000 ;;
6001 esac
6002 ;;
6003 esac
6004 ;;
6005
6006 lynxos*)
6007 # FIXME: insert proper C++ library support
6008 _LT_TAGVAR(ld_shlibs, $1)=no
6009 ;;
6010
6011 m88k*)
6012 # FIXME: insert proper C++ library support
6013 _LT_TAGVAR(ld_shlibs, $1)=no
6014 ;;
6015
6016 mvs*)
6017 case $cc_basename in
6018 cxx*)
6019 # FIXME: insert proper C++ library support
6020 _LT_TAGVAR(ld_shlibs, $1)=no
6021 ;;
6022 *)
6023 # FIXME: insert proper C++ library support
6024 _LT_TAGVAR(ld_shlibs, $1)=no
6025 ;;
6026 esac
6027 ;;
6028
6029 netbsd*)
6030 if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
6031 _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
6032 wlarc=
6033 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
6034 _LT_TAGVAR(hardcode_direct, $1)=yes
6035 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
6036 fi
6037 # Workaround some broken pre-1.5 toolchains
6038 output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
6039 ;;
6040
6041 *nto* | *qnx*)
6042 _LT_TAGVAR(ld_shlibs, $1)=yes
6043 ;;
6044
6045 openbsd2*)
6046 # C++ shared libraries are fairly broken
6047 _LT_TAGVAR(ld_shlibs, $1)=no
6048 ;;
6049
6050 openbsd*)
6051 if test -f /usr/libexec/ld.so; then
6052 _LT_TAGVAR(hardcode_direct, $1)=yes
6053 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
6054 _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
6055 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
6056 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
6057 if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
6058 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
6059 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
6060 _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
6061 fi
6062 output_verbose_link_cmd=echo
6063 else
6064 _LT_TAGVAR(ld_shlibs, $1)=no
6065 fi
6066 ;;
6067
6068 osf3* | osf4* | osf5*)
6069 case $cc_basename in
6070 KCC*)
6071 # Kuck and Associates, Inc. (KAI) C++ Compiler
6072
6073 # KCC will only create a shared library if the output file
6074 # ends with ".so" (or ".sl" for HP-UX), so rename the library
6075 # to its proper name (with version) after linking.
6076 _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
6077
6078 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
6079 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
6080
6081 # Archives containing C++ object files must be created using
6082 # the KAI C++ compiler.
6083 case $host in
6084 osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
6085 *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
6086 esac
6087 ;;
6088 RCC*)
6089 # Rational C++ 2.4.1
6090 # FIXME: insert proper C++ library support
6091 _LT_TAGVAR(ld_shlibs, $1)=no
6092 ;;
6093 cxx*)
6094 case $host in
6095 osf3*)
6096 _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
6097 _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
6098 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
6099 ;;
6100 *)
6101 _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
6102 _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
6103 _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
6104 echo "-hidden">> $lib.exp~
6105 $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
6106 $RM $lib.exp'
6107 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
6108 ;;
6109 esac
6110
6111 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
6112
6113 # Commands to make compiler produce verbose output that lists
6114 # what "hidden" libraries, object files and flags are used when
6115 # linking a shared library.
6116 #
6117 # There doesn't appear to be a way to prevent this compiler from
6118 # explicitly linking system object files so we need to strip them
6119 # from the output so that they don't get included in the library
6120 # dependencies.
6121 output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
6122 ;;
6123 *)
6124 if test "$GXX" = yes && test "$with_gnu_ld" = no; then
6125 _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
6126 case $host in
6127 osf3*)
6128 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
6129 ;;
6130 *)
6131 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
6132 ;;
6133 esac
6134
6135 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
6136 _LT_TAGVAR(hardcode_libdir_separator, $1)=:
6137
6138 # Commands to make compiler produce verbose output that lists
6139 # what "hidden" libraries, object files and flags are used when
6140 # linking a shared library.
6141 output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
6142
6143 else
6144 # FIXME: insert proper C++ library support
6145 _LT_TAGVAR(ld_shlibs, $1)=no
6146 fi
6147 ;;
6148 esac
6149 ;;
6150
6151 psos*)
6152 # FIXME: insert proper C++ library support
6153 _LT_TAGVAR(ld_shlibs, $1)=no
6154 ;;
6155
6156 sunos4*)
6157 case $cc_basename in
6158 CC*)
6159 # Sun C++ 4.x
6160 # FIXME: insert proper C++ library support
6161 _LT_TAGVAR(ld_shlibs, $1)=no
6162 ;;
6163 lcc*)
6164 # Lucid
6165 # FIXME: insert proper C++ library support
6166 _LT_TAGVAR(ld_shlibs, $1)=no
6167 ;;
6168 *)
6169 # FIXME: insert proper C++ library support
6170 _LT_TAGVAR(ld_shlibs, $1)=no
6171 ;;
6172 esac
6173 ;;
6174
6175 solaris*)
6176 case $cc_basename in
6177 CC*)
6178 # Sun C++ 4.2, 5.x and Centerline C++
6179 _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
6180 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
6181 _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
6182 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
6183 $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
6184
6185 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
6186 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
6187 case $host_os in
6188 solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
6189 *)
6190 # The compiler driver will combine and reorder linker options,
6191 # but understands `-z linker_flag'.
6192 # Supported since Solaris 2.6 (maybe 2.5.1?)
6193 _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
6194 ;;
6195 esac
6196 _LT_TAGVAR(link_all_deplibs, $1)=yes
6197
6198 output_verbose_link_cmd='echo'
6199
6200 # Archives containing C++ object files must be created using
6201 # "CC -xar", where "CC" is the Sun C++ compiler. This is
6202 # necessary to make sure instantiated templates are included
6203 # in the archive.
6204 _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
6205 ;;
6206 gcx*)
6207 # Green Hills C++ Compiler
6208 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
6209
6210 # The C++ compiler must be used to create the archive.
6211 _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
6212 ;;
6213 *)
6214 # GNU C++ compiler with Solaris linker
6215 if test "$GXX" = yes && test "$with_gnu_ld" = no; then
6216 _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
6217 if $CC --version | $GREP -v '^2\.7' > /dev/null; then
6218 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
6219 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
6220 $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
6221
6222 # Commands to make compiler produce verbose output that lists
6223 # what "hidden" libraries, object files and flags are used when
6224 # linking a shared library.
6225 output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
6226 else
6227 # g++ 2.7 appears to require `-G' NOT `-shared' on this
6228 # platform.
6229 _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
6230 _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
6231 $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
6232
6233 # Commands to make compiler produce verbose output that lists
6234 # what "hidden" libraries, object files and flags are used when
6235 # linking a shared library.
6236 output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
6237 fi
6238
6239 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
6240 case $host_os in
6241 solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
6242 *)
6243 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
6244 ;;
6245 esac
6246 fi
6247 ;;
6248 esac
6249 ;;
6250
6251 sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
6252 _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
6253 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
6254 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
6255 runpath_var='LD_RUN_PATH'
6256
6257 case $cc_basename in
6258 CC*)
6259 _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6260 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6261 ;;
6262 *)
6263 _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6264 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6265 ;;
6266 esac
6267 ;;
6268
6269 sysv5* | sco3.2v5* | sco5v6*)
6270 # Note: We can NOT use -z defs as we might desire, because we do not
6271 # link with -lc, and that would cause any symbols used from libc to
6272 # always be unresolved, which means just about no library would
6273 # ever link correctly. If we're not using GNU ld we use -z text
6274 # though, which does catch some bad symbols but isn't as heavy-handed
6275 # as -z defs.
6276 _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
6277 _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
6278 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
6279 _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
6280 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
6281 _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
6282 _LT_TAGVAR(link_all_deplibs, $1)=yes
6283 _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
6284 runpath_var='LD_RUN_PATH'
6285
6286 case $cc_basename in
6287 CC*)
6288 _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6289 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6290 ;;
6291 *)
6292 _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6293 _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
6294 ;;
6295 esac
6296 ;;
6297
6298 tandem*)
6299 case $cc_basename in
6300 NCC*)
6301 # NonStop-UX NCC 3.20
6302 # FIXME: insert proper C++ library support
6303 _LT_TAGVAR(ld_shlibs, $1)=no
6304 ;;
6305 *)
6306 # FIXME: insert proper C++ library support
6307 _LT_TAGVAR(ld_shlibs, $1)=no
6308 ;;
6309 esac
6310 ;;
6311
6312 vxworks*)
6313 # FIXME: insert proper C++ library support
6314 _LT_TAGVAR(ld_shlibs, $1)=no
6315 ;;
6316
6317 *)
6318 # FIXME: insert proper C++ library support
6319 _LT_TAGVAR(ld_shlibs, $1)=no
6320 ;;
6321 esac
6322
6323 AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
6324 test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
6325
6326 _LT_TAGVAR(GCC, $1)="$GXX"
6327 _LT_TAGVAR(LD, $1)="$LD"
6328
6329 ## CAVEAT EMPTOR:
6330 ## There is no encapsulation within the following macros, do not change
6331 ## the running order or otherwise move them around unless you know exactly
6332 ## what you are doing...
6333 _LT_SYS_HIDDEN_LIBDEPS($1)
6334 _LT_COMPILER_PIC($1)
6335 _LT_COMPILER_C_O($1)
6336 _LT_COMPILER_FILE_LOCKS($1)
6337 _LT_LINKER_SHLIBS($1)
6338 _LT_SYS_DYNAMIC_LINKER($1)
6339 _LT_LINKER_HARDCODE_LIBPATH($1)
6340
6341 _LT_CONFIG($1)
6342 fi # test -n "$compiler"
6343
6344 CC=$lt_save_CC
6345 LDCXX=$LD
6346 LD=$lt_save_LD
6347 GCC=$lt_save_GCC
6348 with_gnu_ld=$lt_save_with_gnu_ld
6349 lt_cv_path_LDCXX=$lt_cv_path_LD
6350 lt_cv_path_LD=$lt_save_path_LD
6351 lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
6352 lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
6353fi # test "$_lt_caught_CXX_error" != yes
6354
6355AC_LANG_POP
6356])# _LT_LANG_CXX_CONFIG
6357
6358
6359# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
6360# ---------------------------------
6361# Figure out "hidden" library dependencies from verbose
6362# compiler output when linking a shared library.
6363# Parse the compiler output and extract the necessary
6364# objects, libraries and library flags.
6365m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
6366[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
6367# Dependencies to place before and after the object being linked:
6368_LT_TAGVAR(predep_objects, $1)=
6369_LT_TAGVAR(postdep_objects, $1)=
6370_LT_TAGVAR(predeps, $1)=
6371_LT_TAGVAR(postdeps, $1)=
6372_LT_TAGVAR(compiler_lib_search_path, $1)=
6373
6374dnl we can't use the lt_simple_compile_test_code here,
6375dnl because it contains code intended for an executable,
6376dnl not a library. It's possible we should let each
6377dnl tag define a new lt_????_link_test_code variable,
6378dnl but it's only used here...
6379m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
6380int a;
6381void foo (void) { a = 0; }
6382_LT_EOF
6383], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
6384class Foo
6385{
6386public:
6387 Foo (void) { a = 0; }
6388private:
6389 int a;
6390};
6391_LT_EOF
6392], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
6393 subroutine foo
6394 implicit none
6395 integer*4 a
6396 a=0
6397 return
6398 end
6399_LT_EOF
6400], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
6401 subroutine foo
6402 implicit none
6403 integer a
6404 a=0
6405 return
6406 end
6407_LT_EOF
6408], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
6409public class foo {
6410 private int a;
6411 public void bar (void) {
6412 a = 0;
6413 }
6414};
6415_LT_EOF
6416])
6417dnl Parse the compiler output and extract the necessary
6418dnl objects, libraries and library flags.
6419if AC_TRY_EVAL(ac_compile); then
6420 # Parse the compiler output and extract the necessary
6421 # objects, libraries and library flags.
6422
6423 # Sentinel used to keep track of whether or not we are before
6424 # the conftest object file.
6425 pre_test_object_deps_done=no
6426
6427 for p in `eval "$output_verbose_link_cmd"`; do
6428 case $p in
6429
6430 -L* | -R* | -l*)
6431 # Some compilers place space between "-{L,R}" and the path.
6432 # Remove the space.
6433 if test $p = "-L" ||
6434 test $p = "-R"; then
6435 prev=$p
6436 continue
6437 else
6438 prev=
6439 fi
6440
6441 if test "$pre_test_object_deps_done" = no; then
6442 case $p in
6443 -L* | -R*)
6444 # Internal compiler library paths should come after those
6445 # provided the user. The postdeps already come after the
6446 # user supplied libs so there is no need to process them.
6447 if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
6448 _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
6449 else
6450 _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
6451 fi
6452 ;;
6453 # The "-l" case would never come before the object being
6454 # linked, so don't bother handling this case.
6455 esac
6456 else
6457 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
6458 _LT_TAGVAR(postdeps, $1)="${prev}${p}"
6459 else
6460 _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
6461 fi
6462 fi
6463 ;;
6464
6465 *.$objext)
6466 # This assumes that the test object file only shows up
6467 # once in the compiler output.
6468 if test "$p" = "conftest.$objext"; then
6469 pre_test_object_deps_done=yes
6470 continue
6471 fi
6472
6473 if test "$pre_test_object_deps_done" = no; then
6474 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
6475 _LT_TAGVAR(predep_objects, $1)="$p"
6476 else
6477 _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
6478 fi
6479 else
6480 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
6481 _LT_TAGVAR(postdep_objects, $1)="$p"
6482 else
6483 _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
6484 fi
6485 fi
6486 ;;
6487
6488 *) ;; # Ignore the rest.
6489
6490 esac
6491 done
6492
6493 # Clean up.
6494 rm -f a.out a.exe
6495else
6496 echo "libtool.m4: error: problem compiling $1 test program"
6497fi
6498
6499$RM -f confest.$objext
6500
6501# PORTME: override above test on systems where it is broken
6502m4_if([$1], [CXX],
6503[case $host_os in
6504interix[[3-9]]*)
6505 # Interix 3.5 installs completely hosed .la files for C++, so rather than
6506 # hack all around it, let's just trust "g++" to DTRT.
6507 _LT_TAGVAR(predep_objects,$1)=
6508 _LT_TAGVAR(postdep_objects,$1)=
6509 _LT_TAGVAR(postdeps,$1)=
6510 ;;
6511
6512linux*)
6513 case `$CC -V 2>&1 | sed 5q` in
6514 *Sun\ C*)
6515 # Sun C++ 5.9
6516
6517 # The more standards-conforming stlport4 library is
6518 # incompatible with the Cstd library. Avoid specifying
6519 # it if it's in CXXFLAGS. Ignore libCrun as
6520 # -library=stlport4 depends on it.
6521 case " $CXX $CXXFLAGS " in
6522 *" -library=stlport4 "*)
6523 solaris_use_stlport4=yes
6524 ;;
6525 esac
6526
6527 if test "$solaris_use_stlport4" != yes; then
6528 _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
6529 fi
6530 ;;
6531 esac
6532 ;;
6533
6534solaris*)
6535 case $cc_basename in
6536 CC*)
6537 # The more standards-conforming stlport4 library is
6538 # incompatible with the Cstd library. Avoid specifying
6539 # it if it's in CXXFLAGS. Ignore libCrun as
6540 # -library=stlport4 depends on it.
6541 case " $CXX $CXXFLAGS " in
6542 *" -library=stlport4 "*)
6543 solaris_use_stlport4=yes
6544 ;;
6545 esac
6546
6547 # Adding this requires a known-good setup of shared libraries for
6548 # Sun compiler versions before 5.6, else PIC objects from an old
6549 # archive will be linked into the output, leading to subtle bugs.
6550 if test "$solaris_use_stlport4" != yes; then
6551 _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
6552 fi
6553 ;;
6554 esac
6555 ;;
6556esac
6557])
6558
6559case " $_LT_TAGVAR(postdeps, $1) " in
6560*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
6561esac
6562 _LT_TAGVAR(compiler_lib_search_dirs, $1)=
6563if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
6564 _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
6565fi
6566_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
6567 [The directories searched by this compiler when creating a shared library])
6568_LT_TAGDECL([], [predep_objects], [1],
6569 [Dependencies to place before and after the objects being linked to
6570 create a shared library])
6571_LT_TAGDECL([], [postdep_objects], [1])
6572_LT_TAGDECL([], [predeps], [1])
6573_LT_TAGDECL([], [postdeps], [1])
6574_LT_TAGDECL([], [compiler_lib_search_path], [1],
6575 [The library search path used internally by the compiler when linking
6576 a shared library])
6577])# _LT_SYS_HIDDEN_LIBDEPS
6578
6579
6580# _LT_PROG_F77
6581# ------------
6582# Since AC_PROG_F77 is broken, in that it returns the empty string
6583# if there is no fortran compiler, we have our own version here.
6584m4_defun([_LT_PROG_F77],
6585[
6586pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
6587AC_PROG_F77
6588if test -z "$F77" || test "X$F77" = "Xno"; then
6589 _lt_disable_F77=yes
6590fi
6591popdef([AC_MSG_ERROR])
6592])# _LT_PROG_F77
6593
6594dnl aclocal-1.4 backwards compatibility:
6595dnl AC_DEFUN([_LT_PROG_F77], [])
6596
6597
6598# _LT_LANG_F77_CONFIG([TAG])
6599# --------------------------
6600# Ensure that the configuration variables for a Fortran 77 compiler are
6601# suitably defined. These variables are subsequently used by _LT_CONFIG
6602# to write the compiler configuration to `libtool'.
6603m4_defun([_LT_LANG_F77_CONFIG],
6604[AC_REQUIRE([_LT_PROG_F77])dnl
6605AC_LANG_PUSH(Fortran 77)
6606
6607_LT_TAGVAR(archive_cmds_need_lc, $1)=no
6608_LT_TAGVAR(allow_undefined_flag, $1)=
6609_LT_TAGVAR(always_export_symbols, $1)=no
6610_LT_TAGVAR(archive_expsym_cmds, $1)=
6611_LT_TAGVAR(export_dynamic_flag_spec, $1)=
6612_LT_TAGVAR(hardcode_direct, $1)=no
6613_LT_TAGVAR(hardcode_direct_absolute, $1)=no
6614_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
6615_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
6616_LT_TAGVAR(hardcode_libdir_separator, $1)=
6617_LT_TAGVAR(hardcode_minus_L, $1)=no
6618_LT_TAGVAR(hardcode_automatic, $1)=no
6619_LT_TAGVAR(inherit_rpath, $1)=no
6620_LT_TAGVAR(module_cmds, $1)=
6621_LT_TAGVAR(module_expsym_cmds, $1)=
6622_LT_TAGVAR(link_all_deplibs, $1)=unknown
6623_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
6624_LT_TAGVAR(no_undefined_flag, $1)=
6625_LT_TAGVAR(whole_archive_flag_spec, $1)=
6626_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
6627
6628# Source file extension for f77 test sources.
6629ac_ext=f
6630
6631# Object file extension for compiled f77 test sources.
6632objext=o
6633_LT_TAGVAR(objext, $1)=$objext
6634
6635# No sense in running all these tests if we already determined that
6636# the F77 compiler isn't working. Some variables (like enable_shared)
6637# are currently assumed to apply to all compilers on this platform,
6638# and will be corrupted by setting them based on a non-working compiler.
6639if test "$_lt_disable_F77" != yes; then
6640 # Code to be used in simple compile tests
6641 lt_simple_compile_test_code="\
6642 subroutine t
6643 return
6644 end
6645"
6646
6647 # Code to be used in simple link tests
6648 lt_simple_link_test_code="\
6649 program t
6650 end
6651"
6652
6653 # ltmain only uses $CC for tagged configurations so make sure $CC is set.
6654 _LT_TAG_COMPILER
6655
6656 # save warnings/boilerplate of simple test code
6657 _LT_COMPILER_BOILERPLATE
6658 _LT_LINKER_BOILERPLATE
6659
6660 # Allow CC to be a program name with arguments.
6661 lt_save_CC="$CC"
6662 lt_save_GCC=$GCC
6663 CC=${F77-"f77"}
6664 compiler=$CC
6665 _LT_TAGVAR(compiler, $1)=$CC
6666 _LT_CC_BASENAME([$compiler])
6667 GCC=$G77
6668 if test -n "$compiler"; then
6669 AC_MSG_CHECKING([if libtool supports shared libraries])
6670 AC_MSG_RESULT([$can_build_shared])
6671
6672 AC_MSG_CHECKING([whether to build shared libraries])
6673 test "$can_build_shared" = "no" && enable_shared=no
6674
6675 # On AIX, shared libraries and static libraries use the same namespace, and
6676 # are all built from PIC.
6677 case $host_os in
6678 aix3*)
6679 test "$enable_shared" = yes && enable_static=no
6680 if test -n "$RANLIB"; then
6681 archive_cmds="$archive_cmds~\$RANLIB \$lib"
6682 postinstall_cmds='$RANLIB $lib'
6683 fi
6684 ;;
6685 aix[[4-9]]*)
6686 if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
6687 test "$enable_shared" = yes && enable_static=no
6688 fi
6689 ;;
6690 esac
6691 AC_MSG_RESULT([$enable_shared])
6692
6693 AC_MSG_CHECKING([whether to build static libraries])
6694 # Make sure either enable_shared or enable_static is yes.
6695 test "$enable_shared" = yes || enable_static=yes
6696 AC_MSG_RESULT([$enable_static])
6697
6698 _LT_TAGVAR(GCC, $1)="$G77"
6699 _LT_TAGVAR(LD, $1)="$LD"
6700
6701 ## CAVEAT EMPTOR:
6702 ## There is no encapsulation within the following macros, do not change
6703 ## the running order or otherwise move them around unless you know exactly
6704 ## what you are doing...
6705 _LT_COMPILER_PIC($1)
6706 _LT_COMPILER_C_O($1)
6707 _LT_COMPILER_FILE_LOCKS($1)
6708 _LT_LINKER_SHLIBS($1)
6709 _LT_SYS_DYNAMIC_LINKER($1)
6710 _LT_LINKER_HARDCODE_LIBPATH($1)
6711
6712 _LT_CONFIG($1)
6713 fi # test -n "$compiler"
6714
6715 GCC=$lt_save_GCC
6716 CC="$lt_save_CC"
6717fi # test "$_lt_disable_F77" != yes
6718
6719AC_LANG_POP
6720])# _LT_LANG_F77_CONFIG
6721
6722
6723# _LT_PROG_FC
6724# -----------
6725# Since AC_PROG_FC is broken, in that it returns the empty string
6726# if there is no fortran compiler, we have our own version here.
6727m4_defun([_LT_PROG_FC],
6728[
6729pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
6730AC_PROG_FC
6731if test -z "$FC" || test "X$FC" = "Xno"; then
6732 _lt_disable_FC=yes
6733fi
6734popdef([AC_MSG_ERROR])
6735])# _LT_PROG_FC
6736
6737dnl aclocal-1.4 backwards compatibility:
6738dnl AC_DEFUN([_LT_PROG_FC], [])
6739
6740
6741# _LT_LANG_FC_CONFIG([TAG])
6742# -------------------------
6743# Ensure that the configuration variables for a Fortran compiler are
6744# suitably defined. These variables are subsequently used by _LT_CONFIG
6745# to write the compiler configuration to `libtool'.
6746m4_defun([_LT_LANG_FC_CONFIG],
6747[AC_REQUIRE([_LT_PROG_FC])dnl
6748AC_LANG_PUSH(Fortran)
6749
6750_LT_TAGVAR(archive_cmds_need_lc, $1)=no
6751_LT_TAGVAR(allow_undefined_flag, $1)=
6752_LT_TAGVAR(always_export_symbols, $1)=no
6753_LT_TAGVAR(archive_expsym_cmds, $1)=
6754_LT_TAGVAR(export_dynamic_flag_spec, $1)=
6755_LT_TAGVAR(hardcode_direct, $1)=no
6756_LT_TAGVAR(hardcode_direct_absolute, $1)=no
6757_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
6758_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
6759_LT_TAGVAR(hardcode_libdir_separator, $1)=
6760_LT_TAGVAR(hardcode_minus_L, $1)=no
6761_LT_TAGVAR(hardcode_automatic, $1)=no
6762_LT_TAGVAR(inherit_rpath, $1)=no
6763_LT_TAGVAR(module_cmds, $1)=
6764_LT_TAGVAR(module_expsym_cmds, $1)=
6765_LT_TAGVAR(link_all_deplibs, $1)=unknown
6766_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
6767_LT_TAGVAR(no_undefined_flag, $1)=
6768_LT_TAGVAR(whole_archive_flag_spec, $1)=
6769_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
6770
6771# Source file extension for fc test sources.
6772ac_ext=${ac_fc_srcext-f}
6773
6774# Object file extension for compiled fc test sources.
6775objext=o
6776_LT_TAGVAR(objext, $1)=$objext
6777
6778# No sense in running all these tests if we already determined that
6779# the FC compiler isn't working. Some variables (like enable_shared)
6780# are currently assumed to apply to all compilers on this platform,
6781# and will be corrupted by setting them based on a non-working compiler.
6782if test "$_lt_disable_FC" != yes; then
6783 # Code to be used in simple compile tests
6784 lt_simple_compile_test_code="\
6785 subroutine t
6786 return
6787 end
6788"
6789
6790 # Code to be used in simple link tests
6791 lt_simple_link_test_code="\
6792 program t
6793 end
6794"
6795
6796 # ltmain only uses $CC for tagged configurations so make sure $CC is set.
6797 _LT_TAG_COMPILER
6798
6799 # save warnings/boilerplate of simple test code
6800 _LT_COMPILER_BOILERPLATE
6801 _LT_LINKER_BOILERPLATE
6802
6803 # Allow CC to be a program name with arguments.
6804 lt_save_CC="$CC"
6805 lt_save_GCC=$GCC
6806 CC=${FC-"f95"}
6807 compiler=$CC
6808 GCC=$ac_cv_fc_compiler_gnu
6809
6810 _LT_TAGVAR(compiler, $1)=$CC
6811 _LT_CC_BASENAME([$compiler])
6812
6813 if test -n "$compiler"; then
6814 AC_MSG_CHECKING([if libtool supports shared libraries])
6815 AC_MSG_RESULT([$can_build_shared])
6816
6817 AC_MSG_CHECKING([whether to build shared libraries])
6818 test "$can_build_shared" = "no" && enable_shared=no
6819
6820 # On AIX, shared libraries and static libraries use the same namespace, and
6821 # are all built from PIC.
6822 case $host_os in
6823 aix3*)
6824 test "$enable_shared" = yes && enable_static=no
6825 if test -n "$RANLIB"; then
6826 archive_cmds="$archive_cmds~\$RANLIB \$lib"
6827 postinstall_cmds='$RANLIB $lib'
6828 fi
6829 ;;
6830 aix[[4-9]]*)
6831 if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
6832 test "$enable_shared" = yes && enable_static=no
6833 fi
6834 ;;
6835 esac
6836 AC_MSG_RESULT([$enable_shared])
6837
6838 AC_MSG_CHECKING([whether to build static libraries])
6839 # Make sure either enable_shared or enable_static is yes.
6840 test "$enable_shared" = yes || enable_static=yes
6841 AC_MSG_RESULT([$enable_static])
6842
6843 _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
6844 _LT_TAGVAR(LD, $1)="$LD"
6845
6846 ## CAVEAT EMPTOR:
6847 ## There is no encapsulation within the following macros, do not change
6848 ## the running order or otherwise move them around unless you know exactly
6849 ## what you are doing...
6850 _LT_SYS_HIDDEN_LIBDEPS($1)
6851 _LT_COMPILER_PIC($1)
6852 _LT_COMPILER_C_O($1)
6853 _LT_COMPILER_FILE_LOCKS($1)
6854 _LT_LINKER_SHLIBS($1)
6855 _LT_SYS_DYNAMIC_LINKER($1)
6856 _LT_LINKER_HARDCODE_LIBPATH($1)
6857
6858 _LT_CONFIG($1)
6859 fi # test -n "$compiler"
6860
6861 GCC=$lt_save_GCC
6862 CC="$lt_save_CC"
6863fi # test "$_lt_disable_FC" != yes
6864
6865AC_LANG_POP
6866])# _LT_LANG_FC_CONFIG
6867
6868
6869# _LT_LANG_GCJ_CONFIG([TAG])
6870# --------------------------
6871# Ensure that the configuration variables for the GNU Java Compiler compiler
6872# are suitably defined. These variables are subsequently used by _LT_CONFIG
6873# to write the compiler configuration to `libtool'.
6874m4_defun([_LT_LANG_GCJ_CONFIG],
6875[AC_REQUIRE([LT_PROG_GCJ])dnl
6876AC_LANG_SAVE
6877
6878# Source file extension for Java test sources.
6879ac_ext=java
6880
6881# Object file extension for compiled Java test sources.
6882objext=o
6883_LT_TAGVAR(objext, $1)=$objext
6884
6885# Code to be used in simple compile tests
6886lt_simple_compile_test_code="class foo {}"
6887
6888# Code to be used in simple link tests
6889lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
6890
6891# ltmain only uses $CC for tagged configurations so make sure $CC is set.
6892_LT_TAG_COMPILER
6893
6894# save warnings/boilerplate of simple test code
6895_LT_COMPILER_BOILERPLATE
6896_LT_LINKER_BOILERPLATE
6897
6898# Allow CC to be a program name with arguments.
6899lt_save_CC="$CC"
6900lt_save_GCC=$GCC
6901GCC=yes
6902CC=${GCJ-"gcj"}
6903compiler=$CC
6904_LT_TAGVAR(compiler, $1)=$CC
6905_LT_TAGVAR(LD, $1)="$LD"
6906_LT_CC_BASENAME([$compiler])
6907
6908# GCJ did not exist at the time GCC didn't implicitly link libc in.
6909_LT_TAGVAR(archive_cmds_need_lc, $1)=no
6910
6911_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
6912
6913## CAVEAT EMPTOR:
6914## There is no encapsulation within the following macros, do not change
6915## the running order or otherwise move them around unless you know exactly
6916## what you are doing...
6917if test -n "$compiler"; then
6918 _LT_COMPILER_NO_RTTI($1)
6919 _LT_COMPILER_PIC($1)
6920 _LT_COMPILER_C_O($1)
6921 _LT_COMPILER_FILE_LOCKS($1)
6922 _LT_LINKER_SHLIBS($1)
6923 _LT_LINKER_HARDCODE_LIBPATH($1)
6924
6925 _LT_CONFIG($1)
6926fi
6927
6928AC_LANG_RESTORE
6929
6930GCC=$lt_save_GCC
6931CC="$lt_save_CC"
6932])# _LT_LANG_GCJ_CONFIG
6933
6934
6935# _LT_LANG_RC_CONFIG([TAG])
6936# -------------------------
6937# Ensure that the configuration variables for the Windows resource compiler
6938# are suitably defined. These variables are subsequently used by _LT_CONFIG
6939# to write the compiler configuration to `libtool'.
6940m4_defun([_LT_LANG_RC_CONFIG],
6941[AC_REQUIRE([LT_PROG_RC])dnl
6942AC_LANG_SAVE
6943
6944# Source file extension for RC test sources.
6945ac_ext=rc
6946
6947# Object file extension for compiled RC test sources.
6948objext=o
6949_LT_TAGVAR(objext, $1)=$objext
6950
6951# Code to be used in simple compile tests
6952lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
6953
6954# Code to be used in simple link tests
6955lt_simple_link_test_code="$lt_simple_compile_test_code"
6956
6957# ltmain only uses $CC for tagged configurations so make sure $CC is set.
6958_LT_TAG_COMPILER
6959
6960# save warnings/boilerplate of simple test code
6961_LT_COMPILER_BOILERPLATE
6962_LT_LINKER_BOILERPLATE
6963
6964# Allow CC to be a program name with arguments.
6965lt_save_CC="$CC"
6966lt_save_GCC=$GCC
6967GCC=
6968CC=${RC-"windres"}
6969compiler=$CC
6970_LT_TAGVAR(compiler, $1)=$CC
6971_LT_CC_BASENAME([$compiler])
6972_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
6973
6974if test -n "$compiler"; then
6975 :
6976 _LT_CONFIG($1)
6977fi
6978
6979GCC=$lt_save_GCC
6980AC_LANG_RESTORE
6981CC="$lt_save_CC"
6982])# _LT_LANG_RC_CONFIG
6983
6984
6985# LT_PROG_GCJ
6986# -----------
6987AC_DEFUN([LT_PROG_GCJ],
6988[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
6989 [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
6990 [AC_CHECK_TOOL(GCJ, gcj,)
6991 test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
6992 AC_SUBST(GCJFLAGS)])])[]dnl
6993])
6994
6995# Old name:
6996AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
6997dnl aclocal-1.4 backwards compatibility:
6998dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
6999
7000
7001# LT_PROG_RC
7002# ----------
7003AC_DEFUN([LT_PROG_RC],
7004[AC_CHECK_TOOL(RC, windres,)
7005])
7006
7007# Old name:
7008AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
7009dnl aclocal-1.4 backwards compatibility:
7010dnl AC_DEFUN([LT_AC_PROG_RC], [])
7011
7012
7013# _LT_DECL_EGREP
7014# --------------
7015# If we don't have a new enough Autoconf to choose the best grep
7016# available, choose the one first in the user's PATH.
7017m4_defun([_LT_DECL_EGREP],
7018[AC_REQUIRE([AC_PROG_EGREP])dnl
7019AC_REQUIRE([AC_PROG_FGREP])dnl
7020test -z "$GREP" && GREP=grep
7021_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
7022_LT_DECL([], [EGREP], [1], [An ERE matcher])
7023_LT_DECL([], [FGREP], [1], [A literal string matcher])
7024dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
7025AC_SUBST([GREP])
7026])
7027
7028
7029# _LT_DECL_OBJDUMP
7030# --------------
7031# If we don't have a new enough Autoconf to choose the best objdump
7032# available, choose the one first in the user's PATH.
7033m4_defun([_LT_DECL_OBJDUMP],
7034[AC_CHECK_TOOL(OBJDUMP, objdump, false)
7035test -z "$OBJDUMP" && OBJDUMP=objdump
7036_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
7037AC_SUBST([OBJDUMP])
7038])
7039
7040
7041# _LT_DECL_SED
7042# ------------
7043# Check for a fully-functional sed program, that truncates
7044# as few characters as possible. Prefer GNU sed if found.
7045m4_defun([_LT_DECL_SED],
7046[AC_PROG_SED
7047test -z "$SED" && SED=sed
7048Xsed="$SED -e 1s/^X//"
7049_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
7050_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
7051 [Sed that helps us avoid accidentally triggering echo(1) options like -n])
7052])# _LT_DECL_SED
7053
7054m4_ifndef([AC_PROG_SED], [
7055############################################################
7056# NOTE: This macro has been submitted for inclusion into #
7057# GNU Autoconf as AC_PROG_SED. When it is available in #
7058# a released version of Autoconf we should remove this #
7059# macro and use it instead. #
7060############################################################
7061
7062m4_defun([AC_PROG_SED],
7063[AC_MSG_CHECKING([for a sed that does not truncate output])
7064AC_CACHE_VAL(lt_cv_path_SED,
7065[# Loop through the user's path and test for sed and gsed.
7066# Then use that list of sed's as ones to test for truncation.
7067as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
7068for as_dir in $PATH
7069do
7070 IFS=$as_save_IFS
7071 test -z "$as_dir" && as_dir=.
7072 for lt_ac_prog in sed gsed; do
7073 for ac_exec_ext in '' $ac_executable_extensions; do
7074 if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
7075 lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
7076 fi
7077 done
7078 done
7079done
7080IFS=$as_save_IFS
7081lt_ac_max=0
7082lt_ac_count=0
7083# Add /usr/xpg4/bin/sed as it is typically found on Solaris
7084# along with /bin/sed that truncates output.
7085for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
7086 test ! -f $lt_ac_sed && continue
7087 cat /dev/null > conftest.in
7088 lt_ac_count=0
7089 echo $ECHO_N "0123456789$ECHO_C" >conftest.in
7090 # Check for GNU sed and select it if it is found.
7091 if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
7092 lt_cv_path_SED=$lt_ac_sed
7093 break
7094 fi
7095 while true; do
7096 cat conftest.in conftest.in >conftest.tmp
7097 mv conftest.tmp conftest.in
7098 cp conftest.in conftest.nl
7099 echo >>conftest.nl
7100 $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
7101 cmp -s conftest.out conftest.nl || break
7102 # 10000 chars as input seems more than enough
7103 test $lt_ac_count -gt 10 && break
7104 lt_ac_count=`expr $lt_ac_count + 1`
7105 if test $lt_ac_count -gt $lt_ac_max; then
7106 lt_ac_max=$lt_ac_count
7107 lt_cv_path_SED=$lt_ac_sed
7108 fi
7109 done
7110done
7111])
7112SED=$lt_cv_path_SED
7113AC_SUBST([SED])
7114AC_MSG_RESULT([$SED])
7115])#AC_PROG_SED
7116])#m4_ifndef
7117
7118# Old name:
7119AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
7120dnl aclocal-1.4 backwards compatibility:
7121dnl AC_DEFUN([LT_AC_PROG_SED], [])
7122
7123
7124# _LT_CHECK_SHELL_FEATURES
7125# ------------------------
7126# Find out whether the shell is Bourne or XSI compatible,
7127# or has some other useful features.
7128m4_defun([_LT_CHECK_SHELL_FEATURES],
7129[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
7130# Try some XSI features
7131xsi_shell=no
7132( _lt_dummy="a/b/c"
7133 test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
7134 = c,a/b,, \
7135 && eval 'test $(( 1 + 1 )) -eq 2 \
7136 && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
7137 && xsi_shell=yes
7138AC_MSG_RESULT([$xsi_shell])
7139_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
7140
7141AC_MSG_CHECKING([whether the shell understands "+="])
7142lt_shell_append=no
7143( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
7144 >/dev/null 2>&1 \
7145 && lt_shell_append=yes
7146AC_MSG_RESULT([$lt_shell_append])
7147_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
7148
7149if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
7150 lt_unset=unset
7151else
7152 lt_unset=false
7153fi
7154_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
7155
7156# test EBCDIC or ASCII
7157case `echo X|tr X '\101'` in
7158 A) # ASCII based system
7159 # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
7160 lt_SP2NL='tr \040 \012'
7161 lt_NL2SP='tr \015\012 \040\040'
7162 ;;
7163 *) # EBCDIC based system
7164 lt_SP2NL='tr \100 \n'
7165 lt_NL2SP='tr \r\n \100\100'
7166 ;;
7167esac
7168_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
7169_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
7170])# _LT_CHECK_SHELL_FEATURES
7171
7172
7173# _LT_PROG_XSI_SHELLFNS
7174# ---------------------
7175# Bourne and XSI compatible variants of some useful shell functions.
7176m4_defun([_LT_PROG_XSI_SHELLFNS],
7177[case $xsi_shell in
7178 yes)
7179 cat << \_LT_EOF >> "$cfgfile"
7180
7181# func_dirname file append nondir_replacement
7182# Compute the dirname of FILE. If nonempty, add APPEND to the result,
7183# otherwise set result to NONDIR_REPLACEMENT.
7184func_dirname ()
7185{
7186 case ${1} in
7187 */*) func_dirname_result="${1%/*}${2}" ;;
7188 * ) func_dirname_result="${3}" ;;
7189 esac
7190}
7191
7192# func_basename file
7193func_basename ()
7194{
7195 func_basename_result="${1##*/}"
7196}
7197
7198# func_dirname_and_basename file append nondir_replacement
7199# perform func_basename and func_dirname in a single function
7200# call:
7201# dirname: Compute the dirname of FILE. If nonempty,
7202# add APPEND to the result, otherwise set result
7203# to NONDIR_REPLACEMENT.
7204# value returned in "$func_dirname_result"
7205# basename: Compute filename of FILE.
7206# value retuned in "$func_basename_result"
7207# Implementation must be kept synchronized with func_dirname
7208# and func_basename. For efficiency, we do not delegate to
7209# those functions but instead duplicate the functionality here.
7210func_dirname_and_basename ()
7211{
7212 case ${1} in
7213 */*) func_dirname_result="${1%/*}${2}" ;;
7214 * ) func_dirname_result="${3}" ;;
7215 esac
7216 func_basename_result="${1##*/}"
7217}
7218
7219# func_stripname prefix suffix name
7220# strip PREFIX and SUFFIX off of NAME.
7221# PREFIX and SUFFIX must not contain globbing or regex special
7222# characters, hashes, percent signs, but SUFFIX may contain a leading
7223# dot (in which case that matches only a dot).
7224func_stripname ()
7225{
7226 # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
7227 # positional parameters, so assign one to ordinary parameter first.
7228 func_stripname_result=${3}
7229 func_stripname_result=${func_stripname_result#"${1}"}
7230 func_stripname_result=${func_stripname_result%"${2}"}
7231}
7232
7233# func_opt_split
7234func_opt_split ()
7235{
7236 func_opt_split_opt=${1%%=*}
7237 func_opt_split_arg=${1#*=}
7238}
7239
7240# func_lo2o object
7241func_lo2o ()
7242{
7243 case ${1} in
7244 *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
7245 *) func_lo2o_result=${1} ;;
7246 esac
7247}
7248
7249# func_xform libobj-or-source
7250func_xform ()
7251{
7252 func_xform_result=${1%.*}.lo
7253}
7254
7255# func_arith arithmetic-term...
7256func_arith ()
7257{
7258 func_arith_result=$(( $[*] ))
7259}
7260
7261# func_len string
7262# STRING may not start with a hyphen.
7263func_len ()
7264{
7265 func_len_result=${#1}
7266}
7267
7268_LT_EOF
7269 ;;
7270 *) # Bourne compatible functions.
7271 cat << \_LT_EOF >> "$cfgfile"
7272
7273# func_dirname file append nondir_replacement
7274# Compute the dirname of FILE. If nonempty, add APPEND to the result,
7275# otherwise set result to NONDIR_REPLACEMENT.
7276func_dirname ()
7277{
7278 # Extract subdirectory from the argument.
7279 func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
7280 if test "X$func_dirname_result" = "X${1}"; then
7281 func_dirname_result="${3}"
7282 else
7283 func_dirname_result="$func_dirname_result${2}"
7284 fi
7285}
7286
7287# func_basename file
7288func_basename ()
7289{
7290 func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
7291}
7292
7293dnl func_dirname_and_basename
7294dnl A portable version of this function is already defined in general.m4sh
7295dnl so there is no need for it here.
7296
7297# func_stripname prefix suffix name
7298# strip PREFIX and SUFFIX off of NAME.
7299# PREFIX and SUFFIX must not contain globbing or regex special
7300# characters, hashes, percent signs, but SUFFIX may contain a leading
7301# dot (in which case that matches only a dot).
7302# func_strip_suffix prefix name
7303func_stripname ()
7304{
7305 case ${2} in
7306 .*) func_stripname_result=`$ECHO "X${3}" \
7307 | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
7308 *) func_stripname_result=`$ECHO "X${3}" \
7309 | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
7310 esac
7311}
7312
7313# sed scripts:
7314my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
7315my_sed_long_arg='1s/^-[[^=]]*=//'
7316
7317# func_opt_split
7318func_opt_split ()
7319{
7320 func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
7321 func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
7322}
7323
7324# func_lo2o object
7325func_lo2o ()
7326{
7327 func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
7328}
7329
7330# func_xform libobj-or-source
7331func_xform ()
7332{
7333 func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
7334}
7335
7336# func_arith arithmetic-term...
7337func_arith ()
7338{
7339 func_arith_result=`expr "$[@]"`
7340}
7341
7342# func_len string
7343# STRING may not start with a hyphen.
7344func_len ()
7345{
7346 func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
7347}
7348
7349_LT_EOF
7350esac
7351
7352case $lt_shell_append in
7353 yes)
7354 cat << \_LT_EOF >> "$cfgfile"
7355
7356# func_append var value
7357# Append VALUE to the end of shell variable VAR.
7358func_append ()
7359{
7360 eval "$[1]+=\$[2]"
7361}
7362_LT_EOF
7363 ;;
7364 *)
7365 cat << \_LT_EOF >> "$cfgfile"
7366
7367# func_append var value
7368# Append VALUE to the end of shell variable VAR.
7369func_append ()
7370{
7371 eval "$[1]=\$$[1]\$[2]"
7372}
7373
7374_LT_EOF
7375 ;;
7376 esac
7377])
diff --git a/pathologist/m4/ltoptions.m4 b/pathologist/m4/ltoptions.m4
new file mode 100644
index 0000000..34151a3
--- /dev/null
+++ b/pathologist/m4/ltoptions.m4
@@ -0,0 +1,368 @@
1# Helper functions for option handling. -*- Autoconf -*-
2#
3# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
4# Written by Gary V. Vaughan, 2004
5#
6# This file is free software; the Free Software Foundation gives
7# unlimited permission to copy and/or distribute it, with or without
8# modifications, as long as this notice is preserved.
9
10# serial 6 ltoptions.m4
11
12# This is to help aclocal find these macros, as it can't see m4_define.
13AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
14
15
16# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
17# ------------------------------------------
18m4_define([_LT_MANGLE_OPTION],
19[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
20
21
22# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
23# ---------------------------------------
24# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
25# matching handler defined, dispatch to it. Other OPTION-NAMEs are
26# saved as a flag.
27m4_define([_LT_SET_OPTION],
28[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
29m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
30 _LT_MANGLE_DEFUN([$1], [$2]),
31 [m4_warning([Unknown $1 option `$2'])])[]dnl
32])
33
34
35# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
36# ------------------------------------------------------------
37# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
38m4_define([_LT_IF_OPTION],
39[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
40
41
42# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
43# -------------------------------------------------------
44# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
45# are set.
46m4_define([_LT_UNLESS_OPTIONS],
47[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
48 [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
49 [m4_define([$0_found])])])[]dnl
50m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
51])[]dnl
52])
53
54
55# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
56# ----------------------------------------
57# OPTION-LIST is a space-separated list of Libtool options associated
58# with MACRO-NAME. If any OPTION has a matching handler declared with
59# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
60# the unknown option and exit.
61m4_defun([_LT_SET_OPTIONS],
62[# Set options
63m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
64 [_LT_SET_OPTION([$1], _LT_Option)])
65
66m4_if([$1],[LT_INIT],[
67 dnl
68 dnl Simply set some default values (i.e off) if boolean options were not
69 dnl specified:
70 _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
71 ])
72 _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
73 ])
74 dnl
75 dnl If no reference was made to various pairs of opposing options, then
76 dnl we run the default mode handler for the pair. For example, if neither
77 dnl `shared' nor `disable-shared' was passed, we enable building of shared
78 dnl archives by default:
79 _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
80 _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
81 _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
82 _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
83 [_LT_ENABLE_FAST_INSTALL])
84 ])
85])# _LT_SET_OPTIONS
86
87
88## --------------------------------- ##
89## Macros to handle LT_INIT options. ##
90## --------------------------------- ##
91
92# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
93# -----------------------------------------
94m4_define([_LT_MANGLE_DEFUN],
95[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
96
97
98# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
99# -----------------------------------------------
100m4_define([LT_OPTION_DEFINE],
101[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
102])# LT_OPTION_DEFINE
103
104
105# dlopen
106# ------
107LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
108])
109
110AU_DEFUN([AC_LIBTOOL_DLOPEN],
111[_LT_SET_OPTION([LT_INIT], [dlopen])
112AC_DIAGNOSE([obsolete],
113[$0: Remove this warning and the call to _LT_SET_OPTION when you
114put the `dlopen' option into LT_INIT's first parameter.])
115])
116
117dnl aclocal-1.4 backwards compatibility:
118dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
119
120
121# win32-dll
122# ---------
123# Declare package support for building win32 dll's.
124LT_OPTION_DEFINE([LT_INIT], [win32-dll],
125[enable_win32_dll=yes
126
127case $host in
128*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
129 AC_CHECK_TOOL(AS, as, false)
130 AC_CHECK_TOOL(DLLTOOL, dlltool, false)
131 AC_CHECK_TOOL(OBJDUMP, objdump, false)
132 ;;
133esac
134
135test -z "$AS" && AS=as
136_LT_DECL([], [AS], [0], [Assembler program])dnl
137
138test -z "$DLLTOOL" && DLLTOOL=dlltool
139_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
140
141test -z "$OBJDUMP" && OBJDUMP=objdump
142_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
143])# win32-dll
144
145AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
146[AC_REQUIRE([AC_CANONICAL_HOST])dnl
147_LT_SET_OPTION([LT_INIT], [win32-dll])
148AC_DIAGNOSE([obsolete],
149[$0: Remove this warning and the call to _LT_SET_OPTION when you
150put the `win32-dll' option into LT_INIT's first parameter.])
151])
152
153dnl aclocal-1.4 backwards compatibility:
154dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
155
156
157# _LT_ENABLE_SHARED([DEFAULT])
158# ----------------------------
159# implement the --enable-shared flag, and supports the `shared' and
160# `disable-shared' LT_INIT options.
161# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
162m4_define([_LT_ENABLE_SHARED],
163[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
164AC_ARG_ENABLE([shared],
165 [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
166 [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
167 [p=${PACKAGE-default}
168 case $enableval in
169 yes) enable_shared=yes ;;
170 no) enable_shared=no ;;
171 *)
172 enable_shared=no
173 # Look at the argument we got. We use all the common list separators.
174 lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
175 for pkg in $enableval; do
176 IFS="$lt_save_ifs"
177 if test "X$pkg" = "X$p"; then
178 enable_shared=yes
179 fi
180 done
181 IFS="$lt_save_ifs"
182 ;;
183 esac],
184 [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
185
186 _LT_DECL([build_libtool_libs], [enable_shared], [0],
187 [Whether or not to build shared libraries])
188])# _LT_ENABLE_SHARED
189
190LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
191LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
192
193# Old names:
194AC_DEFUN([AC_ENABLE_SHARED],
195[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
196])
197
198AC_DEFUN([AC_DISABLE_SHARED],
199[_LT_SET_OPTION([LT_INIT], [disable-shared])
200])
201
202AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
203AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
204
205dnl aclocal-1.4 backwards compatibility:
206dnl AC_DEFUN([AM_ENABLE_SHARED], [])
207dnl AC_DEFUN([AM_DISABLE_SHARED], [])
208
209
210
211# _LT_ENABLE_STATIC([DEFAULT])
212# ----------------------------
213# implement the --enable-static flag, and support the `static' and
214# `disable-static' LT_INIT options.
215# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
216m4_define([_LT_ENABLE_STATIC],
217[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
218AC_ARG_ENABLE([static],
219 [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
220 [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
221 [p=${PACKAGE-default}
222 case $enableval in
223 yes) enable_static=yes ;;
224 no) enable_static=no ;;
225 *)
226 enable_static=no
227 # Look at the argument we got. We use all the common list separators.
228 lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
229 for pkg in $enableval; do
230 IFS="$lt_save_ifs"
231 if test "X$pkg" = "X$p"; then
232 enable_static=yes
233 fi
234 done
235 IFS="$lt_save_ifs"
236 ;;
237 esac],
238 [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
239
240 _LT_DECL([build_old_libs], [enable_static], [0],
241 [Whether or not to build static libraries])
242])# _LT_ENABLE_STATIC
243
244LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
245LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
246
247# Old names:
248AC_DEFUN([AC_ENABLE_STATIC],
249[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
250])
251
252AC_DEFUN([AC_DISABLE_STATIC],
253[_LT_SET_OPTION([LT_INIT], [disable-static])
254])
255
256AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
257AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
258
259dnl aclocal-1.4 backwards compatibility:
260dnl AC_DEFUN([AM_ENABLE_STATIC], [])
261dnl AC_DEFUN([AM_DISABLE_STATIC], [])
262
263
264
265# _LT_ENABLE_FAST_INSTALL([DEFAULT])
266# ----------------------------------
267# implement the --enable-fast-install flag, and support the `fast-install'
268# and `disable-fast-install' LT_INIT options.
269# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
270m4_define([_LT_ENABLE_FAST_INSTALL],
271[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
272AC_ARG_ENABLE([fast-install],
273 [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
274 [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
275 [p=${PACKAGE-default}
276 case $enableval in
277 yes) enable_fast_install=yes ;;
278 no) enable_fast_install=no ;;
279 *)
280 enable_fast_install=no
281 # Look at the argument we got. We use all the common list separators.
282 lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
283 for pkg in $enableval; do
284 IFS="$lt_save_ifs"
285 if test "X$pkg" = "X$p"; then
286 enable_fast_install=yes
287 fi
288 done
289 IFS="$lt_save_ifs"
290 ;;
291 esac],
292 [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
293
294_LT_DECL([fast_install], [enable_fast_install], [0],
295 [Whether or not to optimize for fast installation])dnl
296])# _LT_ENABLE_FAST_INSTALL
297
298LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
299LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
300
301# Old names:
302AU_DEFUN([AC_ENABLE_FAST_INSTALL],
303[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
304AC_DIAGNOSE([obsolete],
305[$0: Remove this warning and the call to _LT_SET_OPTION when you put
306the `fast-install' option into LT_INIT's first parameter.])
307])
308
309AU_DEFUN([AC_DISABLE_FAST_INSTALL],
310[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
311AC_DIAGNOSE([obsolete],
312[$0: Remove this warning and the call to _LT_SET_OPTION when you put
313the `disable-fast-install' option into LT_INIT's first parameter.])
314])
315
316dnl aclocal-1.4 backwards compatibility:
317dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
318dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
319
320
321# _LT_WITH_PIC([MODE])
322# --------------------
323# implement the --with-pic flag, and support the `pic-only' and `no-pic'
324# LT_INIT options.
325# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
326m4_define([_LT_WITH_PIC],
327[AC_ARG_WITH([pic],
328 [AS_HELP_STRING([--with-pic],
329 [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
330 [pic_mode="$withval"],
331 [pic_mode=default])
332
333test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
334
335_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
336])# _LT_WITH_PIC
337
338LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
339LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
340
341# Old name:
342AU_DEFUN([AC_LIBTOOL_PICMODE],
343[_LT_SET_OPTION([LT_INIT], [pic-only])
344AC_DIAGNOSE([obsolete],
345[$0: Remove this warning and the call to _LT_SET_OPTION when you
346put the `pic-only' option into LT_INIT's first parameter.])
347])
348
349dnl aclocal-1.4 backwards compatibility:
350dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
351
352## ----------------- ##
353## LTDL_INIT Options ##
354## ----------------- ##
355
356m4_define([_LTDL_MODE], [])
357LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
358 [m4_define([_LTDL_MODE], [nonrecursive])])
359LT_OPTION_DEFINE([LTDL_INIT], [recursive],
360 [m4_define([_LTDL_MODE], [recursive])])
361LT_OPTION_DEFINE([LTDL_INIT], [subproject],
362 [m4_define([_LTDL_MODE], [subproject])])
363
364m4_define([_LTDL_TYPE], [])
365LT_OPTION_DEFINE([LTDL_INIT], [installable],
366 [m4_define([_LTDL_TYPE], [installable])])
367LT_OPTION_DEFINE([LTDL_INIT], [convenience],
368 [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/pathologist/m4/ltsugar.m4 b/pathologist/m4/ltsugar.m4
new file mode 100644
index 0000000..9000a05
--- /dev/null
+++ b/pathologist/m4/ltsugar.m4
@@ -0,0 +1,123 @@
1# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
2#
3# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
4# Written by Gary V. Vaughan, 2004
5#
6# This file is free software; the Free Software Foundation gives
7# unlimited permission to copy and/or distribute it, with or without
8# modifications, as long as this notice is preserved.
9
10# serial 6 ltsugar.m4
11
12# This is to help aclocal find these macros, as it can't see m4_define.
13AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
14
15
16# lt_join(SEP, ARG1, [ARG2...])
17# -----------------------------
18# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
19# associated separator.
20# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
21# versions in m4sugar had bugs.
22m4_define([lt_join],
23[m4_if([$#], [1], [],
24 [$#], [2], [[$2]],
25 [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
26m4_define([_lt_join],
27[m4_if([$#$2], [2], [],
28 [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
29
30
31# lt_car(LIST)
32# lt_cdr(LIST)
33# ------------
34# Manipulate m4 lists.
35# These macros are necessary as long as will still need to support
36# Autoconf-2.59 which quotes differently.
37m4_define([lt_car], [[$1]])
38m4_define([lt_cdr],
39[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
40 [$#], 1, [],
41 [m4_dquote(m4_shift($@))])])
42m4_define([lt_unquote], $1)
43
44
45# lt_append(MACRO-NAME, STRING, [SEPARATOR])
46# ------------------------------------------
47# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
48# Note that neither SEPARATOR nor STRING are expanded; they are appended
49# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
50# No SEPARATOR is output if MACRO-NAME was previously undefined (different
51# than defined and empty).
52#
53# This macro is needed until we can rely on Autoconf 2.62, since earlier
54# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
55m4_define([lt_append],
56[m4_define([$1],
57 m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
58
59
60
61# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
62# ----------------------------------------------------------
63# Produce a SEP delimited list of all paired combinations of elements of
64# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
65# has the form PREFIXmINFIXSUFFIXn.
66# Needed until we can rely on m4_combine added in Autoconf 2.62.
67m4_define([lt_combine],
68[m4_if(m4_eval([$# > 3]), [1],
69 [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
70[[m4_foreach([_Lt_prefix], [$2],
71 [m4_foreach([_Lt_suffix],
72 ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
73 [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
74
75
76# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
77# -----------------------------------------------------------------------
78# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
79# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
80m4_define([lt_if_append_uniq],
81[m4_ifdef([$1],
82 [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
83 [lt_append([$1], [$2], [$3])$4],
84 [$5])],
85 [lt_append([$1], [$2], [$3])$4])])
86
87
88# lt_dict_add(DICT, KEY, VALUE)
89# -----------------------------
90m4_define([lt_dict_add],
91[m4_define([$1($2)], [$3])])
92
93
94# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
95# --------------------------------------------
96m4_define([lt_dict_add_subkey],
97[m4_define([$1($2:$3)], [$4])])
98
99
100# lt_dict_fetch(DICT, KEY, [SUBKEY])
101# ----------------------------------
102m4_define([lt_dict_fetch],
103[m4_ifval([$3],
104 m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
105 m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
106
107
108# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
109# -----------------------------------------------------------------
110m4_define([lt_if_dict_fetch],
111[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
112 [$5],
113 [$6])])
114
115
116# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
117# --------------------------------------------------------------
118m4_define([lt_dict_filter],
119[m4_if([$5], [], [],
120 [lt_join(m4_quote(m4_default([$4], [[, ]])),
121 lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
122 [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
123])
diff --git a/pathologist/m4/ltversion.m4 b/pathologist/m4/ltversion.m4
new file mode 100644
index 0000000..f3c5309
--- /dev/null
+++ b/pathologist/m4/ltversion.m4
@@ -0,0 +1,23 @@
1# ltversion.m4 -- version numbers -*- Autoconf -*-
2#
3# Copyright (C) 2004 Free Software Foundation, Inc.
4# Written by Scott James Remnant, 2004
5#
6# This file is free software; the Free Software Foundation gives
7# unlimited permission to copy and/or distribute it, with or without
8# modifications, as long as this notice is preserved.
9
10# Generated from ltversion.in.
11
12# serial 3017 ltversion.m4
13# This file is part of GNU Libtool
14
15m4_define([LT_PACKAGE_VERSION], [2.2.6b])
16m4_define([LT_PACKAGE_REVISION], [1.3017])
17
18AC_DEFUN([LTVERSION_VERSION],
19[macro_version='2.2.6b'
20macro_revision='1.3017'
21_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
22_LT_DECL(, macro_revision, 0)
23])
diff --git a/pathologist/m4/lt~obsolete.m4 b/pathologist/m4/lt~obsolete.m4
new file mode 100644
index 0000000..637bb20
--- /dev/null
+++ b/pathologist/m4/lt~obsolete.m4
@@ -0,0 +1,92 @@
1# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
2#
3# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
4# Written by Scott James Remnant, 2004.
5#
6# This file is free software; the Free Software Foundation gives
7# unlimited permission to copy and/or distribute it, with or without
8# modifications, as long as this notice is preserved.
9
10# serial 4 lt~obsolete.m4
11
12# These exist entirely to fool aclocal when bootstrapping libtool.
13#
14# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
15# which have later been changed to m4_define as they aren't part of the
16# exported API, or moved to Autoconf or Automake where they belong.
17#
18# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
19# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
20# using a macro with the same name in our local m4/libtool.m4 it'll
21# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
22# and doesn't know about Autoconf macros at all.)
23#
24# So we provide this file, which has a silly filename so it's always
25# included after everything else. This provides aclocal with the
26# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
27# because those macros already exist, or will be overwritten later.
28# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
29#
30# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
31# Yes, that means every name once taken will need to remain here until
32# we give up compatibility with versions before 1.7, at which point
33# we need to keep only those names which we still refer to.
34
35# This is to help aclocal find these macros, as it can't see m4_define.
36AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
37
38m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
39m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
40m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
41m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
42m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
43m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
44m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
45m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
46m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
47m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
48m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
49m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
50m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
51m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
52m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
53m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
54m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
55m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
56m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
57m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
58m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
59m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
60m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
61m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
62m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
63m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
64m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
65m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
66m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
67m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
68m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
69m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
70m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
71m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
72m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
73m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
74m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
75m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
76m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
77m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
78m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
79m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
80m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
81m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
82m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
83m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
84m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
85m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
86m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
87m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
88m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
89m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
90m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
91m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
92m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
diff --git a/pathologist/refs/db/bad_memory_access.db b/pathologist/refs/db/bad_memory_access.db
new file mode 100644
index 0000000..8635229
--- /dev/null
+++ b/pathologist/refs/db/bad_memory_access.db
Binary files differ
diff --git a/pathologist/refs/db/bug_assertion_failure.db b/pathologist/refs/db/bug_assertion_failure.db
new file mode 100644
index 0000000..80b952c
--- /dev/null
+++ b/pathologist/refs/db/bug_assertion_failure.db
Binary files differ
diff --git a/pathologist/refs/db/bug_bad_food.db b/pathologist/refs/db/bug_bad_food.db
new file mode 100644
index 0000000..0d0b4dd
--- /dev/null
+++ b/pathologist/refs/db/bug_bad_food.db
Binary files differ
diff --git a/pathologist/refs/db/bug_bad_memory_access.db b/pathologist/refs/db/bug_bad_memory_access.db
new file mode 100644
index 0000000..f5388fd
--- /dev/null
+++ b/pathologist/refs/db/bug_bad_memory_access.db
Binary files differ
diff --git a/pathologist/refs/db/bug_bug_assertion_failure.db b/pathologist/refs/db/bug_bug_assertion_failure.db
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pathologist/refs/db/bug_bug_assertion_failure.db
diff --git a/pathologist/refs/db/bug_division_by_zero_loop.db b/pathologist/refs/db/bug_division_by_zero_loop.db
new file mode 100644
index 0000000..8c103ef
--- /dev/null
+++ b/pathologist/refs/db/bug_division_by_zero_loop.db
Binary files differ
diff --git a/pathologist/refs/db/bug_null_pointer_exception.db b/pathologist/refs/db/bug_null_pointer_exception.db
new file mode 100644
index 0000000..91b1c8a
--- /dev/null
+++ b/pathologist/refs/db/bug_null_pointer_exception.db
Binary files differ
diff --git a/pathologist/refs/db/bug_null_pointer_exception_modified.db b/pathologist/refs/db/bug_null_pointer_exception_modified.db
new file mode 100644
index 0000000..6c264fb
--- /dev/null
+++ b/pathologist/refs/db/bug_null_pointer_exception_modified.db
Binary files differ
diff --git a/pathologist/refs/reports/ref_bt_bug_assertion_failure.xml b/pathologist/refs/reports/ref_bt_bug_assertion_failure.xml
new file mode 100644
index 0000000..9bdccb2
--- /dev/null
+++ b/pathologist/refs/reports/ref_bt_bug_assertion_failure.xml
@@ -0,0 +1,75 @@
1<?xml version="1.0"?>
2<crash category="Assertion Failure" function="assertionFailure" line="9" file="bug_assertion_failure.c" >
3<history><epoch step="0" >
4<trace><function name="assertionFailure" line="9" file="bug_assertion_failure.c" depth="0" >
5<expressions><expression name="assert(x&lt;4)" >
6Not Evaluated</expression>
7<expression name="x&lt;4" >
80</expression>
9<expression name="printf(&quot;Assertion Failure Now!\n&quot;)" >
10Not Evaluated</expression>
11<expression name="x" >
125</expression>
13</expressions>
14</function>
15<function name="main" line="14" file="bug_assertion_failure.c" depth="1" >
16<expressions><expression name="assertionFailure()" >
17Not Evaluated</expression>
18<expression name="argv" >
190xbfffecb4</expression>
20<expression name="argc" >
211</expression>
22</expressions>
23</function>
24</trace>
25</epoch>
26<epoch step="1" >
27<trace><function name="assertionFailure" line="8" file="bug_assertion_failure.c" depth="0" >
28<expressions><expression name="printf(&quot;Assertion Failure Now!\n&quot;)" >
29Not Evaluated</expression>
30<expression name="x" >
315</expression>
32</expressions>
33</function>
34<function name="main" line="14" file="bug_assertion_failure.c" depth="1" >
35<expressions><expression name="assertionFailure()" >
36Not Evaluated</expression>
37<expression name="argv" >
380xbfffecb4</expression>
39<expression name="argc" >
401</expression>
41</expressions>
42</function>
43</trace>
44</epoch>
45<epoch step="2" >
46<trace><function name="assertionFailure" line="7" file="bug_assertion_failure.c" depth="0" >
47<expressions><expression name="x" >
48-1073746936</expression>
49</expressions>
50</function>
51<function name="main" line="14" file="bug_assertion_failure.c" depth="1" >
52<expressions><expression name="assertionFailure()" >
53Not Evaluated</expression>
54<expression name="argv" >
550xbfffecb4</expression>
56<expression name="argc" >
571</expression>
58</expressions>
59</function>
60</trace>
61</epoch>
62<epoch step="3" >
63<trace><function name="main" line="14" file="bug_assertion_failure.c" depth="0" >
64<expressions><expression name="assertionFailure()" >
65Not Evaluated</expression>
66<expression name="argv" >
670xbfffecb4</expression>
68<expression name="argc" >
691</expression>
70</expressions>
71</function>
72</trace>
73</epoch>
74</history>
75</crash>
diff --git a/pathologist/refs/reports/ref_bt_bug_bad_memory_access.xml b/pathologist/refs/reports/ref_bt_bug_bad_memory_access.xml
new file mode 100644
index 0000000..8647995
--- /dev/null
+++ b/pathologist/refs/reports/ref_bt_bug_bad_memory_access.xml
@@ -0,0 +1,103 @@
1<?xml version="1.0"?>
2<crash category="Bad memory access" function="badMemoryAccess" line="9" file="bug_bad_memory_access.c" >
3<valgrind>==10333== Memcheck, a memory error detector
4==10333== Copyright (C) 2002-2010, and GNU GPL&apos;d, by Julian Seward et al.
5==10333== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
6==10333== Command: ../../refs/src/bug_bad_memory_access
7==10333== Parent PID: 10332
8==10333==
9==10333== Invalid write of size 4
10==10333== at 0x80483D0: badMemoryAccess (bug_bad_memory_access.c:9)
11==10333== by 0x80483E2: main (bug_bad_memory_access.c:14)
12==10333== Address 0x4252352 is not stack&apos;d, malloc&apos;d or (recently) free&apos;d
13==10333==
14==10333==
15==10333== Process terminating with default action of signal 11 (SIGSEGV)
16==10333== Access not within mapped region at address 0x4252352
17==10333== at 0x80483D0: badMemoryAccess (bug_bad_memory_access.c:9)
18==10333== by 0x80483E2: main (bug_bad_memory_access.c:14)
19==10333== If you believe this happened as a result of a stack
20==10333== overflow in your program&apos;s main thread (unlikely but
21==10333== possible), you can try to increase the size of the
22==10333== main thread stack using the --main-stacksize= flag.
23==10333== The main thread stack size used in this run was 16777216.
24==10333==
25==10333== HEAP SUMMARY:
26==10333== in use at exit: 0 bytes in 0 blocks
27==10333== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
28==10333==
29==10333== All heap blocks were freed -- no leaks are possible
30==10333==
31==10333== For counts of detected and suppressed errors, rerun with: -v
32==10333== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 6)</valgrind>
33<history><epoch step="0" >
34<trace><function name="badMemoryAccess" line="9" file="bug_bad_memory_access.c" depth="0" >
35<expressions><expression name="*p" >
36Not Evaluated</expression>
37<expression name="printf(&quot;Bad memory access now!\n&quot;)" >
38Not Evaluated</expression>
39<expression name="0x4252352" >
4069542738</expression>
41</expressions>
42</function>
43<function name="main" line="14" file="bug_bad_memory_access.c" depth="1" >
44<expressions><expression name="badMemoryAccess()" >
45Not Evaluated</expression>
46<expression name="argv" >
470xbfffecb4</expression>
48<expression name="argc" >
491</expression>
50</expressions>
51</function>
52</trace>
53</epoch>
54<epoch step="1" >
55<trace><function name="badMemoryAccess" line="8" file="bug_bad_memory_access.c" depth="0" >
56<expressions><expression name="printf(&quot;Bad memory access now!\n&quot;)" >
57Not Evaluated</expression>
58<expression name="0x4252352" >
5969542738</expression>
60</expressions>
61</function>
62<function name="main" line="14" file="bug_bad_memory_access.c" depth="1" >
63<expressions><expression name="badMemoryAccess()" >
64Not Evaluated</expression>
65<expression name="argv" >
660xbfffecb4</expression>
67<expression name="argc" >
681</expression>
69</expressions>
70</function>
71</trace>
72</epoch>
73<epoch step="2" >
74<trace><function name="badMemoryAccess" line="7" file="bug_bad_memory_access.c" depth="0" >
75<expressions><expression name="0x4252352" >
7669542738</expression>
77</expressions>
78</function>
79<function name="main" line="14" file="bug_bad_memory_access.c" depth="1" >
80<expressions><expression name="badMemoryAccess()" >
81Not Evaluated</expression>
82<expression name="argv" >
830xbfffecb4</expression>
84<expression name="argc" >
851</expression>
86</expressions>
87</function>
88</trace>
89</epoch>
90<epoch step="3" >
91<trace><function name="main" line="14" file="bug_bad_memory_access.c" depth="0" >
92<expressions><expression name="badMemoryAccess()" >
93Not Evaluated</expression>
94<expression name="argv" >
950xbfffecb4</expression>
96<expression name="argc" >
971</expression>
98</expressions>
99</function>
100</trace>
101</epoch>
102</history>
103</crash>
diff --git a/pathologist/refs/reports/ref_bt_bug_division_by_zero_depth_1.xml b/pathologist/refs/reports/ref_bt_bug_division_by_zero_depth_1.xml
new file mode 100644
index 0000000..7ae29ed
--- /dev/null
+++ b/pathologist/refs/reports/ref_bt_bug_division_by_zero_depth_1.xml
@@ -0,0 +1,264 @@
1<?xml version="1.0"?>
2<crash category="Division By Zero" function="main" line="14" file="bug_division_by_zero_loop.c" >
3<history><epoch step="0" >
4<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
5<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
6Not Evaluated</expression>
7<expression name="result/k" >
8Not Evaluated</expression>
9<expression name="i&lt;5" >
101</expression>
11<expression name="i" >
121</expression>
13<expression name="printf(&quot;I am alive!\n&quot;)" >
14Not Evaluated</expression>
15<expression name="result" >
16-10</expression>
17<expression name="-1" >
18-1</expression>
19<expression name="k" >
200</expression>
21<expression name="argv" >
220xbfffecb4</expression>
23<expression name="argc" >
241</expression>
25</expressions>
26</function>
27</trace>
28</epoch>
29<epoch step="1" >
30<trace><function name="main" line="13" file="bug_division_by_zero_loop.c" depth="0" >
31<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
32Not Evaluated</expression>
33<expression name="result/k" >
3410</expression>
35<expression name="i&lt;5" >
361</expression>
37<expression name="i" >
381</expression>
39<expression name="printf(&quot;I am alive!\n&quot;)" >
40Not Evaluated</expression>
41<expression name="result" >
42-10</expression>
43<expression name="-1" >
44-1</expression>
45<expression name="k" >
46-1</expression>
47<expression name="argv" >
480xbfffecb4</expression>
49<expression name="argc" >
501</expression>
51</expressions>
52</function>
53</trace>
54</epoch>
55<epoch step="2" >
56<trace><function name="main" line="11" file="bug_division_by_zero_loop.c" depth="0" >
57<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
58Not Evaluated</expression>
59<expression name="result/k" >
6010</expression>
61<expression name="i&lt;5" >
621</expression>
63<expression name="i" >
640</expression>
65<expression name="printf(&quot;I am alive!\n&quot;)" >
66Not Evaluated</expression>
67<expression name="result" >
68-10</expression>
69<expression name="-1" >
70-1</expression>
71<expression name="k" >
72-1</expression>
73<expression name="argv" >
740xbfffecb4</expression>
75<expression name="argc" >
761</expression>
77</expressions>
78</function>
79</trace>
80</epoch>
81<epoch step="3" >
82<trace><function name="main" line="15" file="bug_division_by_zero_loop.c" depth="0" >
83<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
84Not Evaluated</expression>
85<expression name="result/k" >
8610</expression>
87<expression name="i&lt;5" >
881</expression>
89<expression name="i" >
900</expression>
91<expression name="printf(&quot;I am alive!\n&quot;)" >
92Not Evaluated</expression>
93<expression name="result" >
94-10</expression>
95<expression name="-1" >
96-1</expression>
97<expression name="k" >
98-1</expression>
99<expression name="argv" >
1000xbfffecb4</expression>
101<expression name="argc" >
1021</expression>
103</expressions>
104</function>
105</trace>
106</epoch>
107<epoch step="4" >
108<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
109<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
110Not Evaluated</expression>
111<expression name="result/k" >
112-10</expression>
113<expression name="i&lt;5" >
1141</expression>
115<expression name="i" >
1160</expression>
117<expression name="printf(&quot;I am alive!\n&quot;)" >
118Not Evaluated</expression>
119<expression name="result" >
12010</expression>
121<expression name="-1" >
122-1</expression>
123<expression name="k" >
124-1</expression>
125<expression name="argv" >
1260xbfffecb4</expression>
127<expression name="argc" >
1281</expression>
129</expressions>
130</function>
131</trace>
132</epoch>
133<epoch step="5" >
134<trace><function name="main" line="13" file="bug_division_by_zero_loop.c" depth="0" >
135<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
136Not Evaluated</expression>
137<expression name="result/k" >
138-10</expression>
139<expression name="i&lt;5" >
1401</expression>
141<expression name="i" >
1420</expression>
143<expression name="printf(&quot;I am alive!\n&quot;)" >
144Not Evaluated</expression>
145<expression name="result" >
14610</expression>
147<expression name="-1" >
148-1</expression>
149<expression name="k" >
150-1</expression>
151<expression name="argv" >
1520xbfffecb4</expression>
153<expression name="argc" >
1541</expression>
155</expressions>
156</function>
157</trace>
158</epoch>
159<epoch step="6" >
160<trace><function name="main" line="11" file="bug_division_by_zero_loop.c" depth="0" >
161<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
162Not Evaluated</expression>
163<expression name="result/k" >
164-10</expression>
165<expression name="i&lt;5" >
1660</expression>
167<expression name="i" >
1681075441652</expression>
169<expression name="printf(&quot;I am alive!\n&quot;)" >
170Not Evaluated</expression>
171<expression name="result" >
17210</expression>
173<expression name="-1" >
174-1</expression>
175<expression name="k" >
176-1</expression>
177<expression name="argv" >
1780xbfffecb4</expression>
179<expression name="argc" >
1801</expression>
181</expressions>
182</function>
183</trace>
184</epoch>
185<epoch step="7" >
186<trace><function name="main" line="10" file="bug_division_by_zero_loop.c" depth="0" >
187<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
188Not Evaluated</expression>
189<expression name="result/k" >
190-10</expression>
191<expression name="i&lt;5" >
1920</expression>
193<expression name="i" >
1941075441652</expression>
195<expression name="printf(&quot;I am alive!\n&quot;)" >
196Not Evaluated</expression>
197<expression name="result" >
19810</expression>
199<expression name="-1" >
200-1</expression>
201<expression name="k" >
202-1</expression>
203<expression name="argv" >
2040xbfffecb4</expression>
205<expression name="argc" >
2061</expression>
207</expressions>
208</function>
209</trace>
210</epoch>
211<epoch step="8" >
212<trace><function name="main" line="8" file="bug_division_by_zero_loop.c" depth="0" >
213<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
214Not Evaluated</expression>
215<expression name="result/k" >
216-1073801840</expression>
217<expression name="i&lt;5" >
2180</expression>
219<expression name="i" >
2201075441652</expression>
221<expression name="printf(&quot;I am alive!\n&quot;)" >
222Not Evaluated</expression>
223<expression name="result" >
2241073801840</expression>
225<expression name="-1" >
226-1</expression>
227<expression name="k" >
228-1</expression>
229<expression name="argv" >
2300xbfffecb4</expression>
231<expression name="argc" >
2321</expression>
233</expressions>
234</function>
235</trace>
236</epoch>
237<epoch step="9" >
238<trace><function name="main" line="7" file="bug_division_by_zero_loop.c" depth="0" >
239<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
240Not Evaluated</expression>
241<expression name="result/k" >
2427</expression>
243<expression name="i&lt;5" >
2440</expression>
245<expression name="i" >
2461075441652</expression>
247<expression name="printf(&quot;I am alive!\n&quot;)" >
248Not Evaluated</expression>
249<expression name="result" >
2501073801840</expression>
251<expression name="-1" >
252-1</expression>
253<expression name="k" >
254134513787</expression>
255<expression name="argv" >
2560xbfffecb4</expression>
257<expression name="argc" >
2581</expression>
259</expressions>
260</function>
261</trace>
262</epoch>
263</history>
264</crash>
diff --git a/pathologist/refs/reports/ref_bt_bug_division_by_zero_nodepth.xml b/pathologist/refs/reports/ref_bt_bug_division_by_zero_nodepth.xml
new file mode 100644
index 0000000..408cb81
--- /dev/null
+++ b/pathologist/refs/reports/ref_bt_bug_division_by_zero_nodepth.xml
@@ -0,0 +1,130 @@
1<?xml version="1.0"?>
2<crash category="Division By Zero" function="main" line="14" file="bug_division_by_zero_loop.c" >
3<history><epoch step="0" >
4<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
5<expressions><expression name="result/k" >
6Not Evaluated</expression>
7<expression name="i&lt;5" >
81</expression>
9<expression name="i" >
101</expression>
11</expressions>
12</function>
13</trace>
14</epoch>
15<epoch step="1" >
16<trace><function name="main" line="13" file="bug_division_by_zero_loop.c" depth="0" >
17<expressions><expression name="i&lt;5" >
181</expression>
19<expression name="i" >
201</expression>
21</expressions>
22</function>
23</trace>
24</epoch>
25<epoch step="2" >
26<trace><function name="main" line="11" file="bug_division_by_zero_loop.c" depth="0" >
27<expressions><expression name="i&lt;5" >
281</expression>
29<expression name="i" >
300</expression>
31</expressions>
32</function>
33</trace>
34</epoch>
35<epoch step="3" >
36<trace><function name="main" line="15" file="bug_division_by_zero_loop.c" depth="0" >
37<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
38Not Evaluated</expression>
39<expression name="result/k" >
4010</expression>
41<expression name="i&lt;5" >
421</expression>
43<expression name="i" >
440</expression>
45</expressions>
46</function>
47</trace>
48</epoch>
49<epoch step="4" >
50<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
51<expressions><expression name="result/k" >
52-10</expression>
53<expression name="i&lt;5" >
541</expression>
55<expression name="i" >
560</expression>
57</expressions>
58</function>
59</trace>
60</epoch>
61<epoch step="5" >
62<trace><function name="main" line="13" file="bug_division_by_zero_loop.c" depth="0" >
63<expressions><expression name="i&lt;5" >
641</expression>
65<expression name="i" >
660</expression>
67</expressions>
68</function>
69</trace>
70</epoch>
71<epoch step="6" >
72<trace><function name="main" line="11" file="bug_division_by_zero_loop.c" depth="0" >
73<expressions><expression name="i&lt;5" >
740</expression>
75<expression name="i" >
761075441652</expression>
77</expressions>
78</function>
79</trace>
80</epoch>
81<epoch step="7" >
82<trace><function name="main" line="10" file="bug_division_by_zero_loop.c" depth="0" >
83<expressions><expression name="printf(&quot;I am alive!\n&quot;)" >
84Not Evaluated</expression>
85<expression name="result" >
8610</expression>
87<expression name="-1" >
88-1</expression>
89<expression name="k" >
90-1</expression>
91<expression name="argv" >
920xbfffecb4</expression>
93<expression name="argc" >
941</expression>
95</expressions>
96</function>
97</trace>
98</epoch>
99<epoch step="8" >
100<trace><function name="main" line="8" file="bug_division_by_zero_loop.c" depth="0" >
101<expressions><expression name="result" >
1021073801840</expression>
103<expression name="-1" >
104-1</expression>
105<expression name="k" >
106-1</expression>
107<expression name="argv" >
1080xbfffecb4</expression>
109<expression name="argc" >
1101</expression>
111</expressions>
112</function>
113</trace>
114</epoch>
115<epoch step="9" >
116<trace><function name="main" line="7" file="bug_division_by_zero_loop.c" depth="0" >
117<expressions><expression name="-1" >
118-1</expression>
119<expression name="k" >
120134513787</expression>
121<expression name="argv" >
1220xbfffecb4</expression>
123<expression name="argc" >
1241</expression>
125</expressions>
126</function>
127</trace>
128</epoch>
129</history>
130</crash>
diff --git a/pathologist/refs/reports/ref_bt_bug_null_pointer_exception.xml b/pathologist/refs/reports/ref_bt_bug_null_pointer_exception.xml
new file mode 100644
index 0000000..aca18f3
--- /dev/null
+++ b/pathologist/refs/reports/ref_bt_bug_null_pointer_exception.xml
@@ -0,0 +1,79 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue" >
6Not Evaluated</expression>
7<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
8Not Evaluated</expression>
9<expression name="NULL" >
100x0</expression>
11<expression name="crashStruct" >
120x0</expression>
13</expressions>
14</function>
15<function name="main" line="19" file="bug_null_pointer_exception.c" depth="1" >
16<expressions><expression name="crashFunction()" >
17Not Evaluated</expression>
18<expression name="argv" >
190xbfffece4</expression>
20<expression name="argc" >
211</expression>
22</expressions>
23</function>
24</trace>
25</epoch>
26<epoch step="1" >
27<trace><function name="crashFunction" line="13" file="bug_null_pointer_exception.c" depth="0" >
28<expressions><expression name="printf(&quot;Now the program will crash!\n&quot;)" >
29Not Evaluated</expression>
30<expression name="NULL" >
310x0</expression>
32<expression name="crashStruct" >
330x0</expression>
34</expressions>
35</function>
36<function name="main" line="19" file="bug_null_pointer_exception.c" depth="1" >
37<expressions><expression name="crashFunction()" >
38Not Evaluated</expression>
39<expression name="argv" >
400xbfffece4</expression>
41<expression name="argc" >
421</expression>
43</expressions>
44</function>
45</trace>
46</epoch>
47<epoch step="2" >
48<trace><function name="crashFunction" line="12" file="bug_null_pointer_exception.c" depth="0" >
49<expressions><expression name="NULL" >
500x0</expression>
51<expression name="crashStruct" >
520xbfffec38</expression>
53</expressions>
54</function>
55<function name="main" line="19" file="bug_null_pointer_exception.c" depth="1" >
56<expressions><expression name="crashFunction()" >
57Not Evaluated</expression>
58<expression name="argv" >
590xbfffece4</expression>
60<expression name="argc" >
611</expression>
62</expressions>
63</function>
64</trace>
65</epoch>
66<epoch step="3" >
67<trace><function name="main" line="19" file="bug_null_pointer_exception.c" depth="0" >
68<expressions><expression name="crashFunction()" >
69Not Evaluated</expression>
70<expression name="argv" >
710xbfffece4</expression>
72<expression name="argc" >
731</expression>
74</expressions>
75</function>
76</trace>
77</epoch>
78</history>
79</crash>
diff --git a/pathologist/refs/reports/ref_bt_bug_null_pointer_exception_modified.xml b/pathologist/refs/reports/ref_bt_bug_null_pointer_exception_modified.xml
new file mode 100644
index 0000000..b22f5ad
--- /dev/null
+++ b/pathologist/refs/reports/ref_bt_bug_null_pointer_exception_modified.xml
@@ -0,0 +1,197 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="20" file="bug_null_pointer_exception_modified.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="20" file="bug_null_pointer_exception_modified.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue" >
6Not Evaluated</expression>
7<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
8Not Evaluated</expression>
9<expression name="NULL" >
100x0</expression>
11<expression name="crashStruct" >
120x0</expression>
13<expression name="a+b" >
148</expression>
15<expression name="c" >
168</expression>
17<expression name="b" >
185</expression>
19<expression name="a" >
203</expression>
21</expressions>
22</function>
23<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
24<expressions><expression name="crashFunction()" >
25Not Evaluated</expression>
26</expressions>
27</function>
28<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
29<expressions><expression name="intermediateFunction()" >
30Not Evaluated</expression>
31<expression name="argv" >
320xbfffecd4</expression>
33<expression name="argc" >
341</expression>
35</expressions>
36</function>
37</trace>
38</epoch>
39<epoch step="1" >
40<trace><function name="crashFunction" line="19" file="bug_null_pointer_exception_modified.c" depth="0" >
41<expressions><expression name="printf(&quot;Now the program will crash!\n&quot;)" >
42Not Evaluated</expression>
43<expression name="NULL" >
440x0</expression>
45<expression name="crashStruct" >
460x0</expression>
47<expression name="a+b" >
488</expression>
49<expression name="c" >
508</expression>
51<expression name="b" >
525</expression>
53<expression name="a" >
543</expression>
55</expressions>
56</function>
57<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
58<expressions><expression name="crashFunction()" >
59Not Evaluated</expression>
60</expressions>
61</function>
62<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
63<expressions><expression name="intermediateFunction()" >
64Not Evaluated</expression>
65<expression name="argv" >
660xbfffecd4</expression>
67<expression name="argc" >
681</expression>
69</expressions>
70</function>
71</trace>
72</epoch>
73<epoch step="2" >
74<trace><function name="crashFunction" line="18" file="bug_null_pointer_exception_modified.c" depth="0" >
75<expressions><expression name="NULL" >
760x0</expression>
77<expression name="crashStruct" >
780xb7fc0ff4</expression>
79<expression name="a+b" >
808</expression>
81<expression name="c" >
828</expression>
83<expression name="b" >
845</expression>
85<expression name="a" >
863</expression>
87</expressions>
88</function>
89<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
90<expressions><expression name="crashFunction()" >
91Not Evaluated</expression>
92</expressions>
93</function>
94<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
95<expressions><expression name="intermediateFunction()" >
96Not Evaluated</expression>
97<expression name="argv" >
980xbfffecd4</expression>
99<expression name="argc" >
1001</expression>
101</expressions>
102</function>
103</trace>
104</epoch>
105<epoch step="3" >
106<trace><function name="crashFunction" line="17" file="bug_null_pointer_exception_modified.c" depth="0" >
107<expressions><expression name="a+b" >
1088</expression>
109<expression name="c" >
110134520820</expression>
111<expression name="b" >
1125</expression>
113<expression name="a" >
1143</expression>
115</expressions>
116</function>
117<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
118<expressions><expression name="crashFunction()" >
119Not Evaluated</expression>
120</expressions>
121</function>
122<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
123<expressions><expression name="intermediateFunction()" >
124Not Evaluated</expression>
125<expression name="argv" >
1260xbfffecd4</expression>
127<expression name="argc" >
1281</expression>
129</expressions>
130</function>
131</trace>
132</epoch>
133<epoch step="4" >
134<trace><function name="crashFunction" line="16" file="bug_null_pointer_exception_modified.c" depth="0" >
135<expressions><expression name="b" >
136-1073746904</expression>
137<expression name="a" >
1383</expression>
139</expressions>
140</function>
141<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
142<expressions><expression name="crashFunction()" >
143Not Evaluated</expression>
144</expressions>
145</function>
146<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
147<expressions><expression name="intermediateFunction()" >
148Not Evaluated</expression>
149<expression name="argv" >
1500xbfffecd4</expression>
151<expression name="argc" >
1521</expression>
153</expressions>
154</function>
155</trace>
156</epoch>
157<epoch step="5" >
158<trace><function name="crashFunction" line="15" file="bug_null_pointer_exception_modified.c" depth="0" >
159<expressions><expression name="a" >
160134513721</expression>
161</expressions>
162</function>
163<function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="1" >
164<expressions><expression name="crashFunction()" >
165Not Evaluated</expression>
166</expressions>
167</function>
168<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="2" >
169<expressions><expression name="intermediateFunction()" >
170Not Evaluated</expression>
171<expression name="argv" >
1720xbfffecd4</expression>
173<expression name="argc" >
1741</expression>
175</expressions>
176</function>
177</trace>
178</epoch>
179<epoch step="6" >
180<trace><function name="intermediateFunction" line="25" file="bug_null_pointer_exception_modified.c" depth="0" >
181<expressions><expression name="crashFunction()" >
182Not Evaluated</expression>
183</expressions>
184</function>
185<function name="main" line="30" file="bug_null_pointer_exception_modified.c" depth="1" >
186<expressions><expression name="intermediateFunction()" >
187Not Evaluated</expression>
188<expression name="argv" >
1890xbfffecd4</expression>
190<expression name="argc" >
1911</expression>
192</expressions>
193</function>
194</trace>
195</epoch>
196</history>
197</crash>
diff --git a/pathologist/refs/reports/ref_bug_assertion_failure.xml b/pathologist/refs/reports/ref_bug_assertion_failure.xml
new file mode 100644
index 0000000..6117765
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_assertion_failure.xml
@@ -0,0 +1,27 @@
1<?xml version="1.0"?>
2<crash category="Assertion Failure" function="assertionFailure" line="9" file="bug_assertion_failure.c" >
3<history><epoch step="0" >
4<trace><function name="assertionFailure" line="9" file="bug_assertion_failure.c" depth="0" >
5<expressions><expression name="assert(x&lt;4)" >
6Not Evaluated</expression>
7<expression name="x&lt;4" >
80</expression>
9<expression name="printf(&quot;Assertion Failure Now!\n&quot;)" >
10Not Evaluated</expression>
11<expression name="x" >
125</expression>
13</expressions>
14</function>
15<function name="main" line="14" file="bug_assertion_failure.c" depth="1" >
16<expressions><expression name="assertionFailure()" >
17Not Evaluated</expression>
18<expression name="argv" >
190xbfffecf4</expression>
20<expression name="argc" >
211</expression>
22</expressions>
23</function>
24</trace>
25</epoch>
26</history>
27</crash>
diff --git a/pathologist/refs/reports/ref_bug_bad_food.xml b/pathologist/refs/reports/ref_bug_bad_food.xml
new file mode 100644
index 0000000..485a4e0
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_bad_food.xml
@@ -0,0 +1,46 @@
1<?xml version="1.0"?>
2<crash category="Bad memory access" function="main" line="8" file="bug_bad_food.c" >
3<valgrind>==563== Memcheck, a memory error detector
4==563== Copyright (C) 2002-2010, and GNU GPL&apos;d, by Julian Seward et al.
5==563== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
6==563== Command: ../../refs/src/bug_bad_food
7==563== Parent PID: 562
8==563==
9==563== Invalid read of size 4
10==563== at 0x804840D: main (bug_bad_food.c:8)
11==563== Address 0xbaadf00d is not stack&apos;d, malloc&apos;d or (recently) free&apos;d
12==563==
13==563==
14==563== Process terminating with default action of signal 11 (SIGSEGV)
15==563== Access not within mapped region at address 0xBAADF00D
16==563== at 0x804840D: main (bug_bad_food.c:8)
17==563== If you believe this happened as a result of a stack
18==563== overflow in your program&apos;s main thread (unlikely but
19==563== possible), you can try to increase the size of the
20==563== main thread stack using the --main-stacksize= flag.
21==563== The main thread stack size used in this run was 16777216.
22==563==
23==563== HEAP SUMMARY:
24==563== in use at exit: 0 bytes in 0 blocks
25==563== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
26==563==
27==563== All heap blocks were freed -- no leaks are possible
28==563==
29==563== For counts of detected and suppressed errors, rerun with: -v
30==563== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 6)</valgrind>
31<history><epoch step="0" >
32<trace><function name="main" line="8" file="bug_bad_food.c" depth="0" >
33<expressions><expression name="NULL" >
340x0</expression>
35<expression name="0xBAADF00D" >
363131961357</expression>
37<expression name="argv" >
380xbfffecc4</expression>
39<expression name="argc" >
401</expression>
41</expressions>
42</function>
43</trace>
44</epoch>
45</history>
46</crash>
diff --git a/pathologist/refs/reports/ref_bug_bad_memory_access.xml b/pathologist/refs/reports/ref_bug_bad_memory_access.xml
new file mode 100644
index 0000000..bee2441
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_bad_memory_access.xml
@@ -0,0 +1,55 @@
1<?xml version="1.0"?>
2<crash category="Bad memory access" function="badMemoryAccess" line="9" file="bug_bad_memory_access.c" >
3<valgrind>==10321== Memcheck, a memory error detector
4==10321== Copyright (C) 2002-2010, and GNU GPL&apos;d, by Julian Seward et al.
5==10321== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
6==10321== Command: ../../refs/src/bug_bad_memory_access
7==10321== Parent PID: 10320
8==10321==
9==10321== Invalid write of size 4
10==10321== at 0x80483D0: badMemoryAccess (bug_bad_memory_access.c:9)
11==10321== by 0x80483E2: main (bug_bad_memory_access.c:14)
12==10321== Address 0x4252352 is not stack&apos;d, malloc&apos;d or (recently) free&apos;d
13==10321==
14==10321==
15==10321== Process terminating with default action of signal 11 (SIGSEGV)
16==10321== Access not within mapped region at address 0x4252352
17==10321== at 0x80483D0: badMemoryAccess (bug_bad_memory_access.c:9)
18==10321== by 0x80483E2: main (bug_bad_memory_access.c:14)
19==10321== If you believe this happened as a result of a stack
20==10321== overflow in your program&apos;s main thread (unlikely but
21==10321== possible), you can try to increase the size of the
22==10321== main thread stack using the --main-stacksize= flag.
23==10321== The main thread stack size used in this run was 16777216.
24==10321==
25==10321== HEAP SUMMARY:
26==10321== in use at exit: 0 bytes in 0 blocks
27==10321== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
28==10321==
29==10321== All heap blocks were freed -- no leaks are possible
30==10321==
31==10321== For counts of detected and suppressed errors, rerun with: -v
32==10321== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 6)</valgrind>
33<history><epoch step="0" >
34<trace><function name="badMemoryAccess" line="9" file="bug_bad_memory_access.c" depth="0" >
35<expressions><expression name="*p" >
36Not Evaluated</expression>
37<expression name="printf(&quot;Bad memory access now!\n&quot;)" >
38Not Evaluated</expression>
39<expression name="0x4252352" >
4069542738</expression>
41</expressions>
42</function>
43<function name="main" line="14" file="bug_bad_memory_access.c" depth="1" >
44<expressions><expression name="badMemoryAccess()" >
45Not Evaluated</expression>
46<expression name="argv" >
470xbfffecb4</expression>
48<expression name="argc" >
491</expression>
50</expressions>
51</function>
52</trace>
53</epoch>
54</history>
55</crash>
diff --git a/pathologist/refs/reports/ref_bug_division_by_zero_depth_1.xml b/pathologist/refs/reports/ref_bug_division_by_zero_depth_1.xml
new file mode 100644
index 0000000..5095fd0
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_division_by_zero_depth_1.xml
@@ -0,0 +1,30 @@
1<?xml version="1.0"?>
2<crash category="Division By Zero" function="main" line="14" file="bug_division_by_zero_loop.c" >
3<history><epoch step="0" >
4<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
5<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
6Not Evaluated</expression>
7<expression name="result/k" >
8Not Evaluated</expression>
9<expression name="i&lt;5" >
101</expression>
11<expression name="i" >
121</expression>
13<expression name="printf(&quot;I am alive!\n&quot;)" >
14Not Evaluated</expression>
15<expression name="result" >
16-10</expression>
17<expression name="-1" >
18-1</expression>
19<expression name="k" >
200</expression>
21<expression name="argv" >
220xbfffece4</expression>
23<expression name="argc" >
241</expression>
25</expressions>
26</function>
27</trace>
28</epoch>
29</history>
30</crash>
diff --git a/pathologist/refs/reports/ref_bug_division_by_zero_depth_1000.xml b/pathologist/refs/reports/ref_bug_division_by_zero_depth_1000.xml
new file mode 100644
index 0000000..5095fd0
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_division_by_zero_depth_1000.xml
@@ -0,0 +1,30 @@
1<?xml version="1.0"?>
2<crash category="Division By Zero" function="main" line="14" file="bug_division_by_zero_loop.c" >
3<history><epoch step="0" >
4<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
5<expressions><expression name="printf(&quot;result = %d\n&quot;,result)" >
6Not Evaluated</expression>
7<expression name="result/k" >
8Not Evaluated</expression>
9<expression name="i&lt;5" >
101</expression>
11<expression name="i" >
121</expression>
13<expression name="printf(&quot;I am alive!\n&quot;)" >
14Not Evaluated</expression>
15<expression name="result" >
16-10</expression>
17<expression name="-1" >
18-1</expression>
19<expression name="k" >
200</expression>
21<expression name="argv" >
220xbfffece4</expression>
23<expression name="argc" >
241</expression>
25</expressions>
26</function>
27</trace>
28</epoch>
29</history>
30</crash>
diff --git a/pathologist/refs/reports/ref_bug_division_by_zero_nodepth.xml b/pathologist/refs/reports/ref_bug_division_by_zero_nodepth.xml
new file mode 100644
index 0000000..5bf6472
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_division_by_zero_nodepth.xml
@@ -0,0 +1,16 @@
1<?xml version="1.0"?>
2<crash category="Division By Zero" function="main" line="14" file="bug_division_by_zero_loop.c" >
3<history><epoch step="0" >
4<trace><function name="main" line="14" file="bug_division_by_zero_loop.c" depth="0" >
5<expressions><expression name="result/k" >
6Not Evaluated</expression>
7<expression name="i&lt;5" >
81</expression>
9<expression name="i" >
101</expression>
11</expressions>
12</function>
13</trace>
14</epoch>
15</history>
16</crash>
diff --git a/pathologist/refs/reports/ref_bug_null_pointer_exception.xml b/pathologist/refs/reports/ref_bug_null_pointer_exception.xml
new file mode 100644
index 0000000..cced7bd
--- /dev/null
+++ b/pathologist/refs/reports/ref_bug_null_pointer_exception.xml
@@ -0,0 +1,27 @@
1<?xml version="1.0"?>
2<crash category="npe" function="crashFunction" line="14" file="bug_null_pointer_exception.c" >
3<history><epoch step="0" >
4<trace><function name="crashFunction" line="14" file="bug_null_pointer_exception.c" depth="0" >
5<expressions><expression name="crashStruct-&gt;crashValue" >
6Not Evaluated</expression>
7<expression name="printf(&quot;Now the program will crash!\n&quot;)" >
8Not Evaluated</expression>
9<expression name="NULL" >
100x0</expression>
11<expression name="crashStruct" >
120x0</expression>
13</expressions>
14</function>
15<function name="main" line="19" file="bug_null_pointer_exception.c" depth="1" >
16<expressions><expression name="crashFunction()" >
17Not Evaluated</expression>
18<expression name="argv" >
190xbfffece4</expression>
20<expression name="argc" >
211</expression>
22</expressions>
23</function>
24</trace>
25</epoch>
26</history>
27</crash>
diff --git a/pathologist/refs/src/Makefile.am b/pathologist/refs/src/Makefile.am
new file mode 100644
index 0000000..63d622a
--- /dev/null
+++ b/pathologist/refs/src/Makefile.am
@@ -0,0 +1,41 @@
1if MINGW
2 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
3endif
4
5
6if USE_COVERAGE
7 AM_CFLAGS = --coverage -g -O0
8 XLIB = -lgcov
9else
10 AM_CFLAGS = -g -O0
11endif
12
13
14noinst_PROGRAMS =
15 bug_null_pointer_exception \
16 bug_bad_memory_access \
17 bug_assertion_failure \
18 bug_crypto_crc \
19 bug_division_by_zero_loop \
20 bug_null_pointer_exception_modified \
21 bug_sigbus \
22 bug_bad_food
23
24check_PROGRAMS = \
25 bug_null_pointer_exception \
26 bug_bad_memory_access \
27 bug_assertion_failure \
28 bug_crypto_crc \
29 bug_division_by_zero_loop \
30 bug_null_pointer_exception_modified \
31 bug_sigbus \
32 bug_bad_food
33
34bug_null_pointer_exception_SOURCES = bug_null_pointer_exception.c
35bug_bad_memory_access_SOURCES = bug_bad_memory_access.c
36bug_assertion_failure_SOURCES = bug_assertion_failure.c
37bug_crypto_crc_SOURCES = bug_crypto_crc.c
38bug_division_by_zero_loop_SOURCES = bug_division_by_zero_loop.c
39bug_null_pointer_exception_modified_SOURCES = bug_null_pointer_exception_modified.c
40bug_sigbus_SOURCES = bug_sigbus.c
41bug_bad_food_SOURCES = bug_bad_food.c
diff --git a/pathologist/refs/src/bug_assertion_failure.c b/pathologist/refs/src/bug_assertion_failure.c
new file mode 100644
index 0000000..2dbc3f0
--- /dev/null
+++ b/pathologist/refs/src/bug_assertion_failure.c
@@ -0,0 +1,16 @@
1#include <stdio.h>
2#include <assert.h>
3
4void assertionFailure()
5{
6 int x;
7 x = 5;
8 printf("Assertion Failure Now!\n");
9 assert(x < 4);
10}
11
12int main(int argc, char *argv[])
13{
14 assertionFailure();
15 return 0;
16}
diff --git a/pathologist/refs/src/bug_bad_food.c b/pathologist/refs/src/bug_bad_food.c
new file mode 100644
index 0000000..8c4de54
--- /dev/null
+++ b/pathologist/refs/src/bug_bad_food.c
@@ -0,0 +1,11 @@
1#include <stdio.h>
2
3int main(int argc, char **argv)
4{
5 void *badfood = (void*) (long) 0xBAADF00D;
6 void *nil = NULL;
7
8 fprintf (stderr, "%d\n",
9 (int) (long) * (int*) ((1 == argc) ? badfood : nil));
10 return 0;
11}
diff --git a/pathologist/refs/src/bug_bad_memory_access.c b/pathologist/refs/src/bug_bad_memory_access.c
new file mode 100644
index 0000000..54e50ad
--- /dev/null
+++ b/pathologist/refs/src/bug_bad_memory_access.c
@@ -0,0 +1,16 @@
1#include <stdio.h>
2#include <string.h>
3
4
5void badMemoryAccess()
6{
7 int *p = (int*) 0x4252352;
8 printf("Bad memory access now!\n");
9 *p = 5;
10}
11
12int main(int argc, char *argv[])
13{
14 badMemoryAccess();
15 return 0;
16}
diff --git a/pathologist/refs/src/bug_crypto_crc.c b/pathologist/refs/src/bug_crypto_crc.c
new file mode 100644
index 0000000..f252785
--- /dev/null
+++ b/pathologist/refs/src/bug_crypto_crc.c
@@ -0,0 +1,121 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20 For the actual CRC code:
21 Copyright abandoned; this code is in the public domain.
22 Provided to GNUnet by peter@horizon.com
23*/
24
25/**
26 * @file monkey/bug_crypto_crc.c
27 * @brief implementation of CRC32 (this code has been copied from GNUnet util source directory, and modified to be Seaspider friendly)
28 * @author Christian Grothoff, Safey A.Halim
29 */
30
31#include <assert.h>
32#include <stdlib.h>
33#include <stdio.h>
34#include <stdint.h>
35
36#define Z_NULL 0
37
38
39#define POLYNOMIAL (unsigned long)0xedb88320
40static unsigned long crc_table[256];
41
42/*
43 * This routine writes each crc_table entry exactly once,
44 * with the ccorrect final value. Thus, it is safe to call
45 * even on a table that someone else is using concurrently.
46 */
47static void
48crc_init ()
49{
50 static int once;
51 unsigned int i, j;
52 unsigned long h = 1;
53
54 if (once)
55 return;
56 once = 1;
57 crc_table[0] = 0;
58 for (i = 128; i; i >>= 1)
59 {
60 h = (h >> 1) ^ ((h & 1) ? POLYNOMIAL : 0);
61 /* h is now crc_table[i] */
62 for (j = 0; j < 256; j += 2 * i)
63 crc_table[i + j] = crc_table[j] ^ h;
64 }
65}
66
67/*
68 * This computes the standard preset and inverted CRC, as used
69 * by most networking standards. Start by passing in an initial
70 * chaining value of 0, and then pass in the return value from the
71 * previous crc32() call. The final return value is the CRC.
72 * Note that this is a little-endian CRC, which is best used with
73 * data transmitted lsbit-first, and it should, itself, be appended
74 * to data in little-endian byte and bit order to preserve the
75 * property of detecting all burst errors of length 32 bits or less.
76 */
77static unsigned long
78crc_go (unsigned long crc, const char *buf, size_t len)
79{
80 crc_init ();
81 assert (crc_table[255] != 0);
82 crc ^= 0xffffffff;
83 while (len--)
84 crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
85 return crc ^ 0xffffffff;
86}
87
88
89/**
90 * Compute the CRC32 checksum for the first len bytes of the buffer.
91 *
92 * @param buf the data over which we're taking the CRC
93 * @param len the length of the buffer
94 * @return the resulting CRC32 checksum
95 */
96int32_t
97crc32_n (const void *buf, size_t len)
98{
99 unsigned long crc;
100 crc = crc_go (0L, Z_NULL, 0);
101 crc = crc_go (crc, (char *) buf, len);
102 return crc;
103}
104
105
106int main ()
107{
108 char buf[1024];
109 int i;
110 for (i = 0; i < 1024; i++)
111 {
112 buf[i] = (char) i;
113 }
114 for (i = 0; i < 1024; i++)
115 {
116 printf("%d\n", crc32_n (&buf[i], 1024 - i));
117 }
118 return 0;
119}
120
121/* end of bug_crypto_crc.c */
diff --git a/pathologist/refs/src/bug_division_by_zero_loop.c b/pathologist/refs/src/bug_division_by_zero_loop.c
new file mode 100644
index 0000000..544b7d2
--- /dev/null
+++ b/pathologist/refs/src/bug_division_by_zero_loop.c
@@ -0,0 +1,18 @@
1#include <stdio.h>
2
3int
4main (int argc, char *argv[])
5{
6 int i, k, result, tmp;
7 k = -1;
8 result = 10;
9
10 printf("I am alive!\n");
11 for (i = 0; i < 5; i++)
12 {
13 k += i;
14 result = result / k; /* Division by zero in second iteration */
15 printf("result = %d\n", result);
16 }
17 return 0;
18}
diff --git a/pathologist/refs/src/bug_null_pointer_exception.c b/pathologist/refs/src/bug_null_pointer_exception.c
new file mode 100644
index 0000000..4accd65
--- /dev/null
+++ b/pathologist/refs/src/bug_null_pointer_exception.c
@@ -0,0 +1,21 @@
1#include <stdio.h>
2#include <string.h>
3
4
5struct CrashStruct {
6 const char *crashValue;
7};
8
9void crashFunction()
10{
11 struct CrashStruct *crashStruct;
12 crashStruct = NULL;
13 printf("Now the program will crash!\n");
14 crashStruct->crashValue = "hello!";
15}
16
17int main(int argc, char *argv[])
18{
19 crashFunction();
20 return 0;
21}
diff --git a/pathologist/refs/src/bug_null_pointer_exception_modified.c b/pathologist/refs/src/bug_null_pointer_exception_modified.c
new file mode 100644
index 0000000..497b9f0
--- /dev/null
+++ b/pathologist/refs/src/bug_null_pointer_exception_modified.c
@@ -0,0 +1,32 @@
1#include <stdio.h>
2#include <string.h>
3
4
5struct CrashStruct {
6 const char *crashValue;
7};
8
9void crashFunction()
10{
11 struct CrashStruct *crashStruct;
12 int a;
13 int b;
14 int c;
15 a = 3;
16 b = 5;
17 c = a + b;
18 crashStruct = NULL;
19 printf("Now the program will crash!\n");
20 crashStruct->crashValue = "hello!";
21}
22
23void intermediateFunction()
24{
25 crashFunction();
26}
27
28int main(int argc, char *argv[])
29{
30 intermediateFunction();
31 return 0;
32}
diff --git a/pathologist/refs/src/bug_sigbus.c b/pathologist/refs/src/bug_sigbus.c
new file mode 100644
index 0000000..39348ef
--- /dev/null
+++ b/pathologist/refs/src/bug_sigbus.c
@@ -0,0 +1,50 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4
5int main(int argc, char **argv)
6{
7//
8// __asm__("pushf\n"
9// "orl $0x40000, (%esp)\n"
10// "popf");
11
12 int testvar = 0x12345678;
13 int *testvarp;
14
15 testvarp = &testvar;
16 printf("testvarp was %lx\n", testvarp);
17 printf("testvar was %lx\n", *testvarp);
18
19 testvarp = (int *)(((char *)testvarp) + 1);
20 printf("testvarp is %lx\n", testvarp);
21 printf("testvar is %lx\n", *testvarp);
22
23
24// char* str;
25// str = realloc(str,10);
26// */
27//
28// /*
29// char *p;
30//
31// __asm__("pushf\n"
32// "orl $0x40000, (%esp)\n"
33// "popf");
34//
35// /*
36// * malloc() always provides aligned memory.
37// * Do not use stack variable like a[9], depending on the compiler you use,
38// * a may not be aligned properly.
39// */
40// p = malloc(sizeof(int) + 1);
41// memset(p, 0, sizeof(int) + 1);
42//
43// /* making p unaligned */
44// p++;
45//
46// printf("%d\n", *(int *)p);
47//
48// return 0;
49
50}
diff --git a/pathologist/src/Makefile.am b/pathologist/src/Makefile.am
new file mode 100644
index 0000000..d2b35f4
--- /dev/null
+++ b/pathologist/src/Makefile.am
@@ -0,0 +1,2 @@
1SUBDIRS = include mi util minixml pathologist .
2
diff --git a/pathologist/src/include/Makefile.am b/pathologist/src/include/Makefile.am
new file mode 100644
index 0000000..b301e48
--- /dev/null
+++ b/pathologist/src/include/Makefile.am
@@ -0,0 +1,9 @@
1SUBDIRS = .
2
3monkeyincludedir = $(includedir)/monkey
4
5monkeyinclude_HEADERS = \
6 monkey_common.h \
7 plibc.h \
8 gdbmi.h \
9 mxml.h
diff --git a/pathologist/src/include/gdbmi.h b/pathologist/src/include/gdbmi.h
new file mode 100644
index 0000000..588c50b
--- /dev/null
+++ b/pathologist/src/include/gdbmi.h
@@ -0,0 +1,730 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2009 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Comments:
7 Main header for libmigdb.
8
9***************************************************************************/
10
11#ifndef GDBMI_H
12#define GDBMI_H
13
14#ifdef __cplusplus
15extern "C"
16{
17#if 0 /* keep Emacsens' auto-indent happy */
18}
19#endif
20#endif
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h> /* pid_t */
25
26#define MI_OK 0
27#define MI_OUT_OF_MEMORY 1
28#define MI_PIPE_CREATE 2
29#define MI_FORK 3
30#define MI_DEBUGGER_RUN 4
31#define MI_PARSER 5
32#define MI_UNKNOWN_ASYNC 6
33#define MI_UNKNOWN_RESULT 7
34#define MI_FROM_GDB 8
35#define MI_GDB_TIME_OUT 9
36#define MI_GDB_DIED 10
37#define MI_MISSING_XTERM 11
38#define MI_CREATE_TEMPORAL 12
39#define MI_MISSING_GDB 13
40#define MI_LAST_ERROR 13
41
42#define MI_R_NONE 0 /* We are no waiting any response. */
43#define MI_R_SKIP 1 /* We want to discard it. */
44#define MI_R_FE_AND_S 2 /* Wait for done. */
45#define MI_R_E_ARGS 3
46
47enum mi_val_type { t_const, t_tuple, t_list };
48
49/* Types and subtypes. */
50/* Type. */
51#define MI_T_OUT_OF_BAND 0
52#define MI_T_RESULT_RECORD 1
53/* Out of band subtypes. */
54#define MI_ST_ASYNC 0
55#define MI_ST_STREAM 1
56/* Async sub-subtypes. */
57#define MI_SST_EXEC 0
58#define MI_SST_STATUS 1
59#define MI_SST_NOTIFY 2
60/* Stream sub-subtypes. */
61#define MI_SST_CONSOLE 3
62#define MI_SST_TARGET 4
63#define MI_SST_LOG 5
64/* Classes. */
65/* Async classes. */
66#define MI_CL_UNKNOWN 0
67#define MI_CL_STOPPED 1
68#define MI_CL_DOWNLOAD 2
69/* Result classes. */
70#define MI_CL_DONE 2
71#define MI_CL_RUNNING 3
72#define MI_CL_CONNECTED 4
73#define MI_CL_ERROR 5
74#define MI_CL_EXIT 6
75
76#define MI_DEFAULT_TIME_OUT 10
77
78#define MI_DIS_ASM 0
79#define MI_DIS_SRC_ASM 1
80
81/* Implemented workaround for gdb bugs that we can dis/enable. */
82/* At least gdb<=6.1.1 fails to find a source file with absolute path if the
83 name is for a psym instead of a sym. psym==partially loaded symbol table. */
84#define MI_PSYM_SEARCH 0
85
86#define MI_VERSION_STR "0.8.12"
87#define MI_VERSION_MAJOR 0
88#define MI_VERSION_MIDDLE 8
89#define MI_VERSION_MINOR 12
90
91struct mi_results_struct
92{
93 char *var; /* Result name or NULL if just a value. */
94 enum mi_val_type type;
95 union
96 {
97 char *cstr;
98 struct mi_results_struct *rs;
99 } v;
100 struct mi_results_struct *next;
101};
102typedef struct mi_results_struct mi_results;
103
104struct mi_output_struct
105{
106 /* Type of output. */
107 char type;
108 char stype;
109 char sstype;
110 char tclass;
111 /* Content. */
112 mi_results *c;
113 /* Always modeled as a list. */
114 struct mi_output_struct *next;
115};
116typedef struct mi_output_struct mi_output;
117
118typedef void (*stream_cb)(const char *, void *);
119typedef void (*async_cb)(mi_output *o, void *);
120typedef int (*tm_cb)(void *);
121
122/* Values of this structure shouldn't be manipulated by the user. */
123struct mi_h_struct
124{
125 /* Pipes connected to gdb. */
126 int to_gdb[2];
127 int from_gdb[2];
128 /* Streams for the pipes. */
129 FILE *to, *from;
130 /* PID of child gdb. */
131 pid_t pid;
132 char died;
133 /* Which rensponse we are waiting for. */
134 /*int response;*/
135 /* The line we are reading. */
136 char *line;
137 int llen, lread;
138 /* Parsed output. */
139 mi_output *po, *last;
140 /* Tunneled streams callbacks. */
141 stream_cb console;
142 void *console_data;
143 stream_cb target;
144 void *target_data;
145 stream_cb log;
146 void *log_data;
147 /* Async responses callback. */
148 async_cb async;
149 void *async_data;
150 /* Callbacks to get echo of gdb dialog. */
151 stream_cb to_gdb_echo;
152 void *to_gdb_echo_data;
153 stream_cb from_gdb_echo;
154 void *from_gdb_echo_data;
155 /* Time out */
156 tm_cb time_out_cb;
157 void *time_out_cb_data;
158 int time_out;
159 /* Ugly workaround for some of the show responses :-( */
160 int catch_console;
161 char *catched_console;
162 /* MI version, currently unknown but the user can force v2 */
163 unsigned version;
164};
165typedef struct mi_h_struct mi_h;
166
167#define MI_TO(a) ((a)->to_gdb[1])
168
169enum mi_bkp_type { t_unknown=0, t_breakpoint=1, t_hw=2 };
170enum mi_bkp_disp { d_unknown=0, d_keep=1, d_del=2 };
171enum mi_bkp_mode { m_file_line=0, m_function=1, m_file_function=2, m_address=3 };
172
173struct mi_bkpt_struct
174{
175 int number;
176 enum mi_bkp_type type;
177 enum mi_bkp_disp disp; /* keep or del if temporal */
178 char enabled;
179 void *addr;
180 char *func;
181 char *file;
182 int line;
183 int ignore;
184 int times;
185
186 /* For the user: */
187 char *cond;
188 char *file_abs;
189 int thread;
190 enum mi_bkp_mode mode;
191 struct mi_bkpt_struct *next;
192};
193typedef struct mi_bkpt_struct mi_bkpt;
194
195enum mi_wp_mode { wm_unknown=0, wm_write=1, wm_read=2, wm_rw=3 };
196
197struct mi_wp_struct
198{
199 int number;
200 char *exp;
201 enum mi_wp_mode mode;
202
203 /* For the user: */
204 struct mi_wp_struct *next;
205 char enabled;
206};
207typedef struct mi_wp_struct mi_wp;
208
209struct mi_frames_struct
210{
211 int level; /* The frame number, 0 being the topmost frame, i.e. the innermost
212 function. */
213 void *addr; /* The `$pc' value for that frame. */
214 char *func; /* Function name. */
215 char *file; /* File name of the source file where the function lives. */
216 char *from;
217 int line; /* Line number corresponding to the `$pc'. */
218 /* When arguments are available: */
219 mi_results *args;
220 int thread_id;
221 /* When more than one is provided: */
222 struct mi_frames_struct *next;
223};
224typedef struct mi_frames_struct mi_frames;
225
226struct mi_aux_term_struct
227{
228 pid_t pid;
229 char *tty;
230};
231typedef struct mi_aux_term_struct mi_aux_term;
232
233struct mi_pty_struct
234{
235 char *slave;
236 int master;
237};
238typedef struct mi_pty_struct mi_pty;
239
240enum mi_gvar_fmt { fm_natural=0, fm_binary=1, fm_decimal=2, fm_hexadecimal=3,
241 fm_octal=4,
242 /* Only for registers format: */
243 fm_raw=5 };
244enum mi_gvar_lang { lg_unknown=0, lg_c, lg_cpp, lg_java };
245
246#define MI_ATTR_DONT_KNOW 0
247#define MI_ATTR_NONEDITABLE 1
248#define MI_ATTR_EDITABLE 2
249
250struct mi_gvar_struct
251{
252 char *name;
253 int numchild;
254 char *type;
255 enum mi_gvar_fmt format;
256 enum mi_gvar_lang lang;
257 char *exp;
258 int attr;
259
260 /* MI v2 fills it, not yet implemented here. */
261 /* Use gmi_var_evaluate_expression. */
262 char *value;
263
264 /* Pointer to the parent. NULL if none. */
265 struct mi_gvar_struct *parent;
266 /* List containing the children.
267 Filled by gmi_var_list_children.
268 NULL if numchild==0 or not yet filled. */
269 struct mi_gvar_struct *child;
270 /* Next var in the list. */
271 struct mi_gvar_struct *next;
272
273 /* For the user: */
274 char opened; /* We will show its children. 1 when we fill "child" */
275 char changed; /* Needs to be updated. 0 when created. */
276 int vischild; /* How many items visible. numchild when we fill "child" */
277 int depth; /* How deep is this var. */
278 char ispointer;
279};
280typedef struct mi_gvar_struct mi_gvar;
281
282struct mi_gvar_chg_struct
283{
284 char *name;
285 int in_scope; /* if true the other fields apply. */
286 char *new_type; /* NULL if type_changed==false */
287 int new_num_children; /* only when new_type!=NULL */
288
289 struct mi_gvar_chg_struct *next;
290};
291typedef struct mi_gvar_chg_struct mi_gvar_chg;
292
293
294/* A list of assembler instructions. */
295struct mi_asm_insn_struct
296{
297 void *addr;
298 char *func;
299 unsigned offset;
300 char *inst;
301
302 struct mi_asm_insn_struct *next;
303};
304typedef struct mi_asm_insn_struct mi_asm_insn;
305
306/* A list of source lines containing assembler instructions. */
307struct mi_asm_insns_struct
308{
309 char *file;
310 int line;
311 mi_asm_insn *ins;
312
313 struct mi_asm_insns_struct *next;
314};
315typedef struct mi_asm_insns_struct mi_asm_insns;
316
317/* Changed register. */
318struct mi_chg_reg_struct
319{
320 int reg;
321 char *val;
322 char *name;
323 char updated;
324
325 struct mi_chg_reg_struct *next;
326};
327typedef struct mi_chg_reg_struct mi_chg_reg;
328
329/*
330 Examining gdb sources and looking at docs I can see the following "stop"
331reasons:
332
333Breakpoints:
334a) breakpoint-hit (bkptno) + frame
335Also: without reason for temporal breakpoints.
336
337Watchpoints:
338b) watchpoint-trigger (wpt={number,exp};value={old,new}) + frame
339c) read-watchpoint-trigger (hw-rwpt{number,exp};value={value}) + frame
340d) access-watchpoint-trigger (hw-awpt{number,exp};value={[old,]new}) + frame
341e) watchpoint-scope (wpnum) + frame
342
343Movement:
344f) function-finished ([gdb-result-var,return-value]) + frame
345g) location-reached + frame
346h) end-stepping-range + frame
347
348Exit:
349i) exited-signalled (signal-name,signal-meaning)
350j) exited (exit-code)
351k) exited-normally
352
353Signal:
354l) signal-received (signal-name,signal-meaning) + frame
355
356Plus: thread-id
357*/
358enum mi_stop_reason
359{
360 sr_unknown=0,
361 sr_bkpt_hit,
362 sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
363 sr_function_finished, sr_location_reached, sr_end_stepping_range,
364 sr_exited_signalled, sr_exited, sr_exited_normally,
365 sr_signal_received
366};
367
368struct mi_stop_struct
369{
370 enum mi_stop_reason reason; /* If more than one reason just the last. */
371 /* Flags indicating if non-pointer fields are filled. */
372 char have_thread_id;
373 char have_bkptno;
374 char have_exit_code;
375 char have_wpno;
376 /* Where stopped. Doesn't exist for sr_exited*. */
377 int thread_id;
378 mi_frames *frame;
379 /* sr_bkpt_hit */
380 int bkptno;
381 /* sr_*wp_* no scope */
382 mi_wp *wp;
383 char *wp_old;
384 char *wp_val;
385 /* sr_wp_scope */
386 int wpno;
387 /* sr_function_finished. Not for void func. */
388 char *gdb_result_var;
389 char *return_value;
390 /* sr_exited_signalled, sr_signal_received */
391 char *signal_name;
392 char *signal_meaning;
393 /* sr_exited */
394 int exit_code;
395};
396typedef struct mi_stop_struct mi_stop;
397
398/* Variable containing the last error. */
399extern int mi_error;
400extern char *mi_error_from_gdb;
401const char *mi_get_error_str();
402
403/* Indicate the name of gdb exe. Default is /usr/bin/gdb */
404void mi_set_gdb_exe(const char *name);
405const char *mi_get_gdb_exe();
406/* Indicate the name of a file containing commands to send at start-up */
407void mi_set_gdb_start(const char *name);
408const char *mi_get_gdb_start();
409/* Indicate the name of a file containing commands to send after connection */
410void mi_set_gdb_conn(const char *name);
411const char *mi_get_gdb_conn();
412void mi_send_target_commands(mi_h *h);
413/* Connect to a local copy of gdb. */
414mi_h *mi_connect_local();
415/* Close connection. You should ask gdb to quit first. */
416void mi_disconnect(mi_h *h);
417/* Force MI version. */
418#define MI_VERSION2U(maj,mid,min) (maj*0x1000000+mid*0x10000+min)
419void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
420 unsigned vMinor);
421void mi_set_workaround(unsigned wa, int enable);
422int mi_get_workaround(unsigned wa);
423/* Parse gdb output. */
424mi_output *mi_parse_gdb_output(const char *str);
425/* Functions to set/get the tunneled streams callbacks. */
426void mi_set_console_cb(mi_h *h, stream_cb cb, void *data);
427void mi_set_target_cb(mi_h *h, stream_cb cb, void *data);
428void mi_set_log_cb(mi_h *h, stream_cb cb, void *data);
429stream_cb mi_get_console_cb(mi_h *h, void **data);
430stream_cb mi_get_target_cb(mi_h *h, void **data);
431stream_cb mi_get_log_cb(mi_h *h, void **data);
432/* The callback to deal with async events. */
433void mi_set_async_cb(mi_h *h, async_cb cb, void *data);
434async_cb mi_get_async_cb(mi_h *h, void **data);
435/* Time out in gdb responses. */
436void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data);
437tm_cb mi_get_time_out_cb(mi_h *h, void **data);
438void mi_set_time_out(mi_h *h, int to);
439int mi_get_time_out(mi_h *h);
440/* Callbacks to "see" the dialog with gdb. */
441void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data);
442void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data);
443stream_cb mi_get_to_gdb_cb(mi_h *h, void **data);
444stream_cb mi_get_from_gdb_cb(mi_h *h, void **data);
445/* Sends a message to gdb. */
446int mi_send(mi_h *h, const char *format, ...);
447/* Wait until gdb sends a response. */
448mi_output *mi_get_response_blk(mi_h *h);
449/* Check if gdb sent a complete response. Use with mi_retire_response. */
450int mi_get_response(mi_h *h);
451/* Get the last response. Use with mi_get_response. */
452mi_output *mi_retire_response(mi_h *h);
453/* Look for a result record in gdb output. */
454mi_output *mi_get_rrecord(mi_output *r);
455/* Look if the output contains an async stop.
456 If that's the case return the reason for the stop.
457 If the output contains an error the description is returned in reason. */
458int mi_get_async_stop_reason(mi_output *r, char **reason);
459mi_stop *mi_get_stopped(mi_results *r);
460mi_frames *mi_get_async_frame(mi_output *r);
461/* Wait until gdb sends a response.
462 Then check if the response is of the desired type. */
463int mi_res_simple_exit(mi_h *h);
464int mi_res_simple_done(mi_h *h);
465int mi_res_simple_running(mi_h *h);
466int mi_res_simple_connected(mi_h *h);
467/* It additionally extracts an specified variable. */
468mi_results *mi_res_done_var(mi_h *h, const char *var);
469/* Extract a frames list from the response. */
470mi_frames *mi_res_frames_array(mi_h *h, const char *var);
471mi_frames *mi_res_frames_list(mi_h *h);
472mi_frames *mi_parse_frame(mi_results *c);
473mi_frames *mi_res_frame(mi_h *h);
474/* Create an auxiliar terminal using xterm. */
475mi_aux_term *gmi_start_xterm();
476/* Indicate the name of xterm exe. Default is /usr/bin/X11/xterm */
477void mi_set_xterm_exe(const char *name);
478const char *mi_get_xterm_exe();
479/* Kill the auxiliar terminal and release the structure. */
480void gmi_end_aux_term(mi_aux_term *t);
481/* Look for a free Linux VT for the child. */
482mi_aux_term *gmi_look_for_free_vt();
483/* Look for a free and usable Linux VT. */
484int mi_look_for_free_vt();
485/* Close master and release the structure. */
486void gmi_end_pty(mi_pty *p);
487/* Look for a free pseudo terminal. */
488mi_pty *gmi_look_for_free_pty();
489/* Extract a list of thread IDs from response. */
490int mi_res_thread_ids(mi_h *h, int **list);
491int mi_get_thread_ids(mi_output *res, int **list);
492/* A variable response. */
493mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression);
494enum mi_gvar_fmt mi_format_str_to_enum(const char *format);
495const char *mi_format_enum_to_str(enum mi_gvar_fmt format);
496char mi_format_enum_to_char(enum mi_gvar_fmt format);
497enum mi_gvar_lang mi_lang_str_to_enum(const char *lang);
498const char *mi_lang_enum_to_str(enum mi_gvar_lang lang);
499int mi_res_changelist(mi_h *h, mi_gvar_chg **changed);
500int mi_res_children(mi_h *h, mi_gvar *v);
501mi_bkpt *mi_res_bkpt(mi_h *h);
502mi_wp *mi_res_wp(mi_h *h);
503char *mi_res_value(mi_h *h);
504mi_stop *mi_res_stop(mi_h *h);
505enum mi_stop_reason mi_reason_str_to_enum(const char *s);
506const char *mi_reason_enum_to_str(enum mi_stop_reason r);
507int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
508 unsigned long *addr);
509mi_asm_insns *mi_get_asm_insns(mi_h *h);
510/* Starting point of the program. */
511void mi_set_main_func(const char *name);
512const char *mi_get_main_func();
513mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many);
514int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l);
515mi_chg_reg *mi_get_list_changed_regs(mi_h *h);
516int mi_get_reg_values(mi_h *h, mi_chg_reg *l);
517mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many);
518int gmi_target_download(mi_h *h);
519
520/* Allocation functions: */
521void *mi_calloc(size_t count, size_t sz);
522void *mi_calloc1(size_t sz);
523char *mi_malloc(size_t sz);
524mi_results *mi_alloc_results(void);
525mi_output *mi_alloc_output(void);
526mi_frames *mi_alloc_frames(void);
527mi_gvar *mi_alloc_gvar(void);
528mi_gvar_chg *mi_alloc_gvar_chg(void);
529mi_bkpt *mi_alloc_bkpt(void);
530mi_wp *mi_alloc_wp(void);
531mi_stop *mi_alloc_stop(void);
532mi_asm_insns *mi_alloc_asm_insns(void);
533mi_asm_insn *mi_alloc_asm_insn(void);
534mi_chg_reg *mi_alloc_chg_reg(void);
535void mi_free_output(mi_output *r);
536void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r);
537void mi_free_frames(mi_frames *f);
538void mi_free_aux_term(mi_aux_term *t);
539void mi_free_results(mi_results *r);
540void mi_free_results_but(mi_results *r, mi_results *no);
541void mi_free_gvar(mi_gvar *v);
542void mi_free_gvar_chg(mi_gvar_chg *p);
543void mi_free_wp(mi_wp *wp);
544void mi_free_stop(mi_stop *s);
545void mi_free_asm_insns(mi_asm_insns *i);
546void mi_free_asm_insn(mi_asm_insn *i);
547void mi_free_charp_list(char **l);
548void mi_free_chg_reg(mi_chg_reg *r);
549
550/* Porgram control: */
551/* Specify the executable and arguments for local debug. */
552int gmi_set_unwind_on_signal_on(mi_h * h);
553int gmi_set_exec(mi_h *h, const char *file, const char *args);
554/* Start running the executable. Remote sessions starts running. */
555int gmi_exec_run(mi_h *h);
556/* Continue the execution after a "stop". */
557int gmi_exec_continue(mi_h *h);
558/* Continue the execution in reverse order after a "stop". */
559int gmi_exec_continue_reverse(mi_h *h);
560/* Indicate which terminal will use the target program. For local sessions. */
561int gmi_target_terminal(mi_h *h, const char *tty_name);
562/* Specify what's the local copy that have debug info. For remote sessions. */
563int gmi_file_symbol_file(mi_h *h, const char *file);
564/* Continue until function return, the return value is included in the async
565 response. */
566int gmi_exec_finish(mi_h *h);
567/* Continue backwardly until function return, the return value is included in
568 the async response.*/
569int gmi_exec_finish_reverse(mi_h *h);
570/* Stop the program using SIGINT. */
571int gmi_exec_interrupt(mi_h *h);
572/* Next line of code. */
573int gmi_exec_next(mi_h *h);
574/* Start recording a process */
575int gmi_exec_record_process(mi_h *h);
576/* Stop recording a process */
577int gmi_exec_record_stop(mi_h *h);
578/* Next count lines of code. */
579int gmi_exec_next_cnt(mi_h *h, int count);
580/* Next line of assembler code. */
581int gmi_exec_next_instruction(mi_h *h);
582/* Next line of code. Get inside functions. */
583int gmi_exec_step(mi_h *h);
584/* Previous line of code. Get inside functions. */
585int gmi_exec_step_back(mi_h *h);
586/* Previous line of code (do not step into).*/
587int gmi_exec_next_reverse(mi_h *h);
588/* Next count lines of code. Get inside functions. */
589int gmi_exec_step_cnt(mi_h *h, int count);
590/* Next line of assembler code. Get inside calls. */
591int gmi_exec_step_instruction(mi_h *h);
592/* Execute until location is reached. If file is NULL then is until next line. */
593int gmi_exec_until(mi_h *h, const char *file, int line);
594int gmi_exec_until_addr(mi_h *h, void *addr);
595/* Return to previous frame inmediatly. */
596mi_frames *gmi_exec_return(mi_h *h);
597/* Just kill the program. Please read the notes in prg_control.c. */
598int gmi_exec_kill(mi_h *h);
599
600/* Target manipulation: */
601/* Connect to a remote gdbserver using the specified methode. */
602int gmi_target_select(mi_h *h, const char *type, const char *params);
603/* Attach to an already running process. */
604mi_frames *gmi_target_attach(mi_h *h, pid_t pid);
605/* Detach from an attached process. */
606int gmi_target_detach(mi_h *h);
607
608/* Miscellaneous commands: */
609/* Exit gdb killing the child is it is running. */
610void gmi_gdb_exit(mi_h *h);
611/* Send the version to the console. */
612int gmi_gdb_version(mi_h *h);
613/* Set a gdb variable. */
614int gmi_gdb_set(mi_h *h, const char *var, const char *val);
615/* Get a gdb variable. */
616char *gmi_gdb_show(mi_h *h, const char *var);
617
618/* Breakpoints manipulation: */
619/* Insert a breakpoint at file:line. */
620mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line);
621/* Insert a breakpoint, all available options. */
622mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
623 const char *cond, int count, int thread,
624 const char *where);
625mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
626 int temporary, int hard_assist,
627 const char *cond, int count, int thread);
628/* Remove a breakpoint. */
629int gmi_break_delete(mi_h *h, int number);
630/* Free the memory used for a breakpoint description. */
631void mi_free_bkpt(mi_bkpt *b);
632/* Modify the "ignore" count for a breakpoint. */
633int gmi_break_set_times(mi_h *h, int number, int count);
634/* Associate a condition with the breakpoint. */
635int gmi_break_set_condition(mi_h *h, int number, const char *condition);
636/* Enable or disable a breakpoint. */
637int gmi_break_state(mi_h *h, int number, int enable);
638/* Set a watchpoint. It doesn't work for remote targets! */
639mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp);
640
641/* Data Manipulation. */
642/* Evaluate an expression. Returns a parsed tree. */
643char *gmi_data_evaluate_expression(mi_h *h, const char *expression);
644/* Path for sources. */
645int gmi_dir(mi_h *h, const char *path);
646/* A very limited "data read memory" implementation. */
647int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
648 unsigned char *dest, int *na, int convAddr,
649 unsigned long *addr);
650mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
651 const char *end, int mode);
652mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
653 int lines, int mode);
654mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many);
655int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l);
656mi_chg_reg *gmi_data_list_changed_registers(mi_h *h);
657int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l);
658mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many);
659
660/* Stack manipulation. */
661/* List of frames. Arguments aren't filled. */
662mi_frames *gmi_stack_list_frames(mi_h *h);
663/* List of frames. Indicating a range. */
664mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to);
665/* List arguments. Only level and args filled. */
666mi_frames *gmi_stack_list_arguments(mi_h *h, int show);
667/* List arguments. Indicating a range. Only level and args filled. */
668mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to);
669/* Information about the current frame, including args. */
670mi_frames *gmi_stack_info_frame(mi_h *h);
671/* Stack info depth. error => -1 */
672int gmi_stack_info_depth_get(mi_h *h);
673/* Set stack info depth. error => -1 */
674int gmi_stack_info_depth(mi_h *h, int max_depth);
675/* Change current frame. */
676int gmi_stack_select_frame(mi_h *h, int framenum);
677/* List of local vars. */
678mi_results *gmi_stack_list_locals(mi_h *h, int show);
679
680/* Thread. */
681/* List available thread ids. */
682int gmi_thread_list_ids(mi_h *h, int **list);
683/* Select a thread. */
684mi_frames *gmi_thread_select(mi_h *h, int id);
685/* List available threads. */
686mi_frames *gmi_thread_list_all_threads(mi_h *h);
687
688/* Variable objects. */
689/* Create a variable object. */
690mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp);
691mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp);
692/* Create the variable and also fill the lang and attr fields. */
693mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp);
694/* Delete a variable object. Doesn't free the mi_gvar data. */
695int gmi_var_delete(mi_h *h, mi_gvar *var);
696/* Set the format used to represent the result. */
697int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format);
698/* Fill the format field with info from gdb. */
699int gmi_var_show_format(mi_h *h, mi_gvar *var);
700/* Fill the numchild field with info from gdb. */
701int gmi_var_info_num_children(mi_h *h, mi_gvar *var);
702/* Fill the type field with info from gdb. */
703int gmi_var_info_type(mi_h *h, mi_gvar *var);
704/* Fill the expression and lang fields with info from gdb.
705 Note that lang isn't filled during creation. */
706int gmi_var_info_expression(mi_h *h, mi_gvar *var);
707/* Fill the attr field with info from gdb.
708 Note that attr isn't filled during creation. */
709int gmi_var_show_attributes(mi_h *h, mi_gvar *var);
710/* Update variable. Use NULL for all.
711 Note that *changed can be NULL if none updated. */
712int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed);
713/* Change variable. Fills the value field. */
714int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression);
715/* Get current value for a variable. */
716int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var);
717/* List children. It ONLY returns the first level information. :-( */
718int gmi_var_list_children(mi_h *h, mi_gvar *var);
719
720
721
722
723#if 0 /* keep Emacsens' auto-indent happy */
724{
725#endif
726#ifdef __cplusplus
727}
728#endif
729
730#endif
diff --git a/pathologist/src/include/monkey_common.h b/pathologist/src/include/monkey_common.h
new file mode 100644
index 0000000..4973ac5
--- /dev/null
+++ b/pathologist/src/include/monkey_common.h
@@ -0,0 +1,443 @@
1/**
2 * @file monkey_common.h
3 * @brief commonly used definitions
4 * @author Safey A.Halim
5 */
6
7#ifndef MONKEY_COMMON_H
8#define MONKEY_COMMON_H
9
10#include <stdio.h>
11/**
12 * Named constants for return values.
13 */
14#define MONKEY_OK 1
15#define MONKEY_SYSERR -1
16#define MONKEY_YES 1
17#define MONKEY_NO 0
18
19/**
20 * Use this for fatal errors that cannot be handled
21 */
22#define MONKEY_assert(cond) do { if (! (cond)) { fprintf(stderr, "Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } } while(0)
23
24/**
25 * Use this for fatal errors that cannot be handled
26 */
27#define MONKEY_assert_at(cond, f, l) do { if (! (cond)) { fprintf(stderr, "Assertion failed at %s:%d.\n", f, l); abort(); } } while(0)
28
29/**
30 * Use this for internal assertion violations that are
31 * not fatal (can be handled) but should not occur.
32 */
33#define MONKEY_break(cond) do { if (! (cond)) { fprintf(stderr, "Assertion failed at %s:%d.\n", __FILE__, __LINE__); } } while(0)
34
35
36/* ******************** doubly-linked list *************** */
37/* To avoid mistakes: head->prev == tail->next == NULL */
38
39/**
40 * Insert an element at the head of a DLL. Assumes that head, tail and
41 * element are structs with prev and next fields.
42 *
43 * @param head pointer to the head of the DLL
44 * @param tail pointer to the tail of the DLL
45 * @param element element to insert
46 */
47#define MONKEY_CONTAINER_DLL_insert(head,tail,element) do { \
48 MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
49 MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
50 (element)->next = (head); \
51 (element)->prev = NULL; \
52 if ((tail) == NULL) \
53 (tail) = element; \
54 else \
55 (head)->prev = element; \
56 (head) = (element); } while (0)
57
58
59/**
60 * Insert an element at the tail of a DLL. Assumes that head, tail and
61 * element are structs with prev and next fields.
62 *
63 * @param head pointer to the head of the DLL
64 * @param tail pointer to the tail of the DLL
65 * @param element element to insert
66 */
67#define MONKEY_CONTAINER_DLL_insert_tail(head,tail,element) do { \
68 MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
69 MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
70 (element)->prev = (tail); \
71 (element)->next = NULL; \
72 if ((head) == NULL) \
73 (head) = element; \
74 else \
75 (tail)->next = element; \
76 (tail) = (element); } while (0)
77
78
79/**
80 * Insert an element into a DLL after the given other element. Insert
81 * at the head if the other element is NULL.
82 *
83 * @param head pointer to the head of the DLL
84 * @param tail pointer to the tail of the DLL
85 * @param other prior element, NULL for insertion at head of DLL
86 * @param element element to insert
87 */
88#define MONKEY_CONTAINER_DLL_insert_after(head,tail,other,element) do { \
89 MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
90 MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
91 (element)->prev = (other); \
92 if (NULL == other) \
93 { \
94 (element)->next = (head); \
95 (head) = (element); \
96 } \
97 else \
98 { \
99 (element)->next = (other)->next; \
100 (other)->next = (element); \
101 } \
102 if (NULL == (element)->next) \
103 (tail) = (element); \
104 else \
105 (element)->next->prev = (element); } while (0)
106
107
108/**
109 * Insert an element into a DLL before the given other element. Insert
110 * at the tail if the other element is NULL.
111 *
112 * @param head pointer to the head of the DLL
113 * @param tail pointer to the tail of the DLL
114 * @param other prior element, NULL for insertion at head of DLL
115 * @param element element to insert
116 */
117#define MONKEY_CONTAINER_DLL_insert_before(head,tail,other,element) do { \
118 MONKEY_assert ( ( (element)->prev == NULL) && ((head) != (element))); \
119 MONKEY_assert ( ( (element)->next == NULL) && ((tail) != (element))); \
120 (element)->next = (other); \
121 if (NULL == other) \
122 { \
123 (element)->prev = (tail); \
124 (tail) = (element); \
125 } \
126 else \
127 { \
128 (element)->prev = (other)->prev; \
129 (other)->prev = (element); \
130 } \
131 if (NULL == (element)->prev) \
132 (head) = (element); \
133 else \
134 (element)->prev->next = (element); } while (0)
135
136
137/**
138 * Remove an element from a DLL. Assumes
139 * that head, tail and element are structs
140 * with prev and next fields.
141 *
142 * @param head pointer to the head of the DLL
143 * @param tail pointer to the tail of the DLL
144 * @param element element to remove
145 */
146#define MONKEY_CONTAINER_DLL_remove(head,tail,element) do { \
147 MONKEY_assert ( ( (element)->prev != NULL) || ((head) == (element))); \
148 MONKEY_assert ( ( (element)->next != NULL) || ((tail) == (element))); \
149 if ((element)->prev == NULL) \
150 (head) = (element)->next; \
151 else \
152 (element)->prev->next = (element)->next; \
153 if ((element)->next == NULL) \
154 (tail) = (element)->prev; \
155 else \
156 (element)->next->prev = (element)->prev; \
157 (element)->next = NULL; \
158 (element)->prev = NULL; } while (0)
159
160
161#define MONKEY_MIN(a,b) (((a) < (b)) ? (a) : (b))
162
163#define MONKEY_MAX(a,b) (((a) > (b)) ? (a) : (b))
164
165/* ************************* allocation functions ****************** */
166
167/**
168 * Maximum allocation with MONKEY_malloc macro.
169 */
170#define MONKEY_MAX_MALLOC_CHECKED (1024 * 1024 * 40)
171
172/**
173 * Wrapper around malloc. Allocates size bytes of memory.
174 * The memory will be zero'ed out.
175 *
176 * @param size the number of bytes to allocate, must be
177 * smaller than 40 MB.
178 * @return pointer to size bytes of memory, never NULL (!)
179 */
180#define MONKEY_malloc(size) MONKEY_xmalloc_(size, __FILE__, __LINE__)
181
182/**
183 * Allocate and initialize a block of memory.
184 *
185 * @param buf data to initalize the block with
186 * @param size the number of bytes in buf (and size of the allocation)
187 * @return pointer to size bytes of memory, never NULL (!)
188 */
189#define MONKEY_memdup(buf,size) MONKEY_xmemdup_(buf, size, __FILE__, __LINE__)
190
191/**
192 * Wrapper around malloc. Allocates size bytes of memory.
193 * The memory will be zero'ed out.
194 *
195 * @param size the number of bytes to allocate
196 * @return pointer to size bytes of memory, NULL if we do not have enough memory
197 */
198#define MONKEY_malloc_large(size) MONKEY_xmalloc_unchecked_(size, __FILE__, __LINE__)
199
200/**
201 * Wrapper around realloc. Rellocates size bytes of memory.
202 *
203 * @param ptr the pointer to reallocate
204 * @param size the number of bytes to reallocate
205 * @return pointer to size bytes of memory
206 */
207#define MONKEY_realloc(ptr, size) MONKEY_xrealloc_(ptr, size, __FILE__, __LINE__)
208
209/**
210 * Wrapper around free. Frees the memory referred to by ptr.
211 * Note that is is generally better to free memory that was
212 * allocated with MONKEY_array_grow using MONKEY_array_grow(mem, size, 0) instead of MONKEY_free.
213 *
214 * @param ptr location where to free the memory. ptr must have
215 * been returned by MONKEY_strdup, MONKEY_strndup, MONKEY_malloc or MONKEY_array_grow earlier.
216 */
217#define MONKEY_free(ptr) MONKEY_xfree_(ptr, __FILE__, __LINE__)
218
219/**
220 * Free the memory pointed to by ptr if ptr is not NULL.
221 * Equivalent to if (ptr!=null)MONKEY_free(ptr).
222 *
223 * @param ptr the location in memory to free
224 */
225#define MONKEY_free_non_null(ptr) do { void * __x__ = ptr; if (__x__ != NULL) { MONKEY_free(__x__); } } while(0)
226
227/**
228 * Wrapper around MONKEY_strdup. Makes a copy of the zero-terminated string
229 * pointed to by a.
230 *
231 * @param a pointer to a zero-terminated string
232 * @return a copy of the string including zero-termination
233 */
234#define MONKEY_strdup(a) MONKEY_xstrdup_(a,__FILE__,__LINE__)
235
236/**
237 * Wrapper around MONKEY_strndup. Makes a partial copy of the string
238 * pointed to by a.
239 *
240 * @param a pointer to a string
241 * @param length of the string to duplicate
242 * @return a partial copy of the string including zero-termination
243 */
244#define MONKEY_strndup(a,length) MONKEY_xstrndup_(a,length,__FILE__,__LINE__)
245
246/**
247 * Grow a well-typed (!) array. This is a convenience
248 * method to grow a vector <tt>arr</tt> of size <tt>size</tt>
249 * to the new (target) size <tt>tsize</tt>.
250 * <p>
251 *
252 * Example (simple, well-typed stack):
253 *
254 * <pre>
255 * static struct foo * myVector = NULL;
256 * static int myVecLen = 0;
257 *
258 * static void push(struct foo * elem) {
259 * MONKEY_array_grow(myVector, myVecLen, myVecLen+1);
260 * memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
261 * }
262 *
263 * static void pop(struct foo * elem) {
264 * if (myVecLen == 0) die();
265 * memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
266 * MONKEY_array_grow(myVector, myVecLen, myVecLen-1);
267 * }
268 * </pre>
269 *
270 * @param arr base-pointer of the vector, may be NULL if size is 0;
271 * will be updated to reflect the new address. The TYPE of
272 * arr is important since size is the number of elements and
273 * not the size in bytes
274 * @param size the number of elements in the existing vector (number
275 * of elements to copy over)
276 * @param tsize the target size for the resulting vector, use 0 to
277 * free the vector (then, arr will be NULL afterwards).
278 */
279#define MONKEY_array_grow(arr,size,tsize) MONKEY_xgrow_((void**)&arr, sizeof(arr[0]), &size, tsize, __FILE__, __LINE__)
280
281/**
282 * Append an element to a list (growing the
283 * list by one).
284 */
285#define MONKEY_array_append(arr,size,element) do { MONKEY_array_grow(arr,size,size+1); arr[size-1] = element; } while(0)
286
287/**
288 * Like snprintf, just aborts if the buffer is of insufficient size.
289 *
290 * @param buf pointer to buffer that is written to
291 * @param size number of bytes in buf
292 * @param format format strings
293 * @param ... data for format string
294 * @return number of bytes written to buf or negative value on error
295 */
296int
297MONKEY_snprintf (char *buf, size_t size, const char *format, ...);
298
299
300/**
301 * Like asprintf, just portable.
302 *
303 * @param buf set to a buffer of sufficient size (allocated, caller must free)
304 * @param format format string (see printf, fprintf, etc.)
305 * @param ... data for format string
306 * @return number of bytes in "*buf" excluding 0-termination
307 */
308int
309MONKEY_asprintf (char **buf, const char *format, ...);
310
311
312/**
313 * Replace all occurrences of a substring in a string
314 * @param string target string
315 * @param substr substring to replace
316 * @param replacement substitution of the substring
317 */
318char *
319MONKEY_str_replace_all ( const char *string, const char *substr, const char *replacement );
320
321/* ************** internal implementations, use macros above! ************** */
322
323/**
324 * Allocate memory. Checks the return value, aborts if no more
325 * memory is available. Don't use MONKEY_xmalloc_ directly. Use the
326 * MONKEY_malloc macro.
327 * The memory will be zero'ed out.
328 *
329 * @param size number of bytes to allocate
330 * @param filename where is this call being made (for debugging)
331 * @param linenumber line where this call is being made (for debugging)
332 * @return allocated memory, never NULL
333 */
334void *
335MONKEY_xmalloc_ (size_t size, const char *filename, int linenumber);
336
337
338
339/**
340 * Allocate and initialize memory. Checks the return value, aborts if no more
341 * memory is available. Don't use MONKEY_xmemdup_ directly. Use the
342 * MONKEY_memdup macro.
343 *
344 * @param buf buffer to initialize from (must contain size bytes)
345 * @param size number of bytes to allocate
346 * @param filename where is this call being made (for debugging)
347 * @param linenumber line where this call is being made (for debugging)
348 * @return allocated memory, never NULL
349 */
350void *
351MONKEY_xmemdup_ (const void *buf, size_t size, const char *filename,
352 int linenumber);
353
354
355/**
356 * Allocate memory. This function does not check if the allocation
357 * request is within reasonable bounds, allowing allocations larger
358 * than 40 MB. If you don't expect the possibility of very large
359 * allocations, use MONKEY_malloc instead. The memory will be zero'ed
360 * out.
361 *
362 * @param size number of bytes to allocate
363 * @param filename where is this call being made (for debugging)
364 * @param linenumber line where this call is being made (for debugging)
365 * @return pointer to size bytes of memory, NULL if we do not have enough memory
366 */
367void *
368MONKEY_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber);
369
370/**
371 * Reallocate memory. Checks the return value, aborts if no more
372 * memory is available.
373 */
374void *
375MONKEY_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber);
376
377/**
378 * Free memory. Merely a wrapper for the case that we
379 * want to keep track of allocations. Don't use MONKEY_xfree_
380 * directly. Use the MONKEY_free macro.
381 *
382 * @param ptr pointer to memory to free
383 * @param filename where is this call being made (for debugging)
384 * @param linenumber line where this call is being made (for debugging)
385 */
386void
387MONKEY_xfree_ (void *ptr, const char *filename, int linenumber);
388
389
390/**
391 * Dup a string. Don't call MONKEY_xstrdup_ directly. Use the MONKEY_strdup macro.
392 * @param str string to duplicate
393 * @param filename where is this call being made (for debugging)
394 * @param linenumber line where this call is being made (for debugging)
395 * @return the duplicated string
396 */
397char *
398MONKEY_xstrdup_ (const char *str, const char *filename, int linenumber);
399
400/**
401 * Dup partially a string. Don't call MONKEY_xstrndup_ directly. Use the MONKEY_strndup macro.
402 *
403 * @param str string to duplicate
404 * @param len length of the string to duplicate
405 * @param filename where is this call being made (for debugging)
406 * @param linenumber line where this call is being made (for debugging)
407 * @return the duplicated string
408 */
409char *
410MONKEY_xstrndup_ (const char *str, size_t len, const char *filename,
411 int linenumber);
412
413/**
414 * Grow an array, the new elements are zeroed out.
415 * Grows old by (*oldCount-newCount)*elementSize
416 * bytes and sets *oldCount to newCount.
417 *
418 * Don't call MONKEY_xgrow_ directly. Use the MONKEY_array_grow macro.
419 *
420 * @param old address of the pointer to the array
421 * *old may be NULL
422 * @param elementSize the size of the elements of the array
423 * @param oldCount address of the number of elements in the *old array
424 * @param newCount number of elements in the new array, may be 0 (then *old will be NULL afterwards)
425 * @param filename where is this call being made (for debugging)
426 * @param linenumber line where this call is being made (for debugging)
427 */
428void
429MONKEY_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
430 unsigned int newCount, const char *filename, int linenumber);
431
432
433
434
435#if __STDC_VERSION__ < 199901L
436#if __GNUC__ >= 2
437#define __func__ __FUNCTION__
438#else
439#define __func__ "<unknown>"
440#endif
441#endif
442
443#endif /* MONKEY_COMMON_H */
diff --git a/pathologist/src/include/monkey_getopt_lib.h b/pathologist/src/include/monkey_getopt_lib.h
new file mode 100644
index 0000000..50d9cc1
--- /dev/null
+++ b/pathologist/src/include/monkey_getopt_lib.h
@@ -0,0 +1,367 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file include/gnunet_getopt_lib.h
23 * @brief command line parsing and --help formatting
24 *
25 * @author Christian Grothoff
26 */
27
28#ifndef MONKEY_GETOPT_LIB_H
29#define MONKEY_GETOPT_LIB_H
30
31#ifdef __cplusplus
32extern "C"
33{
34#if 0 /* keep Emacsens' auto-indent happy */
35}
36#endif
37#endif
38
39//#include "gnunet_configuration_lib.h"
40
41/**
42 * @brief General context for command line processors.
43 */
44struct MONKEY_GETOPT_CommandLineProcessorContext
45{
46
47 /**
48 * Name of the application
49 */
50 const char *binaryName;
51
52 /**
53 * Name of application with option summary
54 */
55 const char *binaryOptions;
56
57 /**
58 * Array with all command line options.
59 */
60 const struct MONKEY_GETOPT_CommandLineOption *allOptions;
61
62 /**
63 * Original command line
64 */
65 char *const *argv;
66
67 /**
68 * Total number of argv's.
69 */
70 unsigned int argc;
71
72 /**
73 * Current argument.
74 */
75 unsigned int currentArgument;
76
77};
78
79/**
80 * @brief Process a command line option
81 *
82 * @param ctx context for all options
83 * @param scls specific closure (for this processor)
84 * @param option long name of the option (i.e. "config" for --config)
85 * @param value argument, NULL if none was given
86 * @return MONKEY_OK to continue processing other options, MONKEY_SYSERR to abort
87 */
88typedef int (*MONKEY_GETOPT_CommandLineOptionProcessor) (struct
89 MONKEY_GETOPT_CommandLineProcessorContext
90 * ctx, void *scls,
91 const char *option,
92 const char *value);
93
94/**
95 * @brief Definition of a command line option.
96 */
97struct MONKEY_GETOPT_CommandLineOption
98{
99
100 /**
101 * Short name of the option (use '\\0' for none).
102 */
103 const char shortName;
104
105 /**
106 * Long name of the option (may not be NULL)
107 */
108 const char *name;
109
110 /**
111 * Name of the argument for the user in help text
112 */
113 const char *argumentHelp;
114
115 /**
116 * Help text for the option (description)
117 */
118 const char *description;
119
120 /**
121 * Is an argument required? 0: MONKEY_NO (includes optional), 1: MONKEY_YES.
122 */
123 int require_argument;
124
125 /**
126 * Handler for the option.
127 */
128 MONKEY_GETOPT_CommandLineOptionProcessor processor;
129
130 /**
131 * Specific closure to pass to the processor.
132 */
133 void *scls;
134
135};
136
137/**
138 * Macro defining the option to print the command line
139 * help text (-h option).
140 *
141 * @param about string with brief description of the application
142 */
143#define MONKEY_GETOPT_OPTION_HELP(about) \
144 { 'h', "help", (const char *) NULL, gettext_noop("print this help"), 0, &MONKEY_GETOPT_format_help_, (void *) about }
145
146
147/**
148 * Macro defining the option to print the version of
149 * the application (-v option)
150 *
151 * @param version string with the version number
152 */
153#define MONKEY_GETOPT_OPTION_VERSION(version) \
154 { 'v', "version", (const char *) NULL, gettext_noop("print the version number"), 0, &MONKEY_GETOPT_print_version_, (void *) version }
155
156
157/**
158 * Allow user to specify log file name (-l option)
159 *
160 * @param logfn set to the name of the logfile
161 */
162#define MONKEY_GETOPT_OPTION_LOGFILE(logfn) \
163 { 'l', "logfile", "LOGFILE", gettext_noop("configure logging to write logs to LOGFILE"), 1, &MONKEY_GETOPT_set_string, (void *) logfn }
164
165
166/**
167 * Allow user to specify log level (-L option)
168 *
169 * @param loglev set to the log level
170 */
171#define MONKEY_GETOPT_OPTION_LOGLEVEL(loglev) \
172 { 'L', "log", "LOGLEVEL", gettext_noop("configure logging to use LOGLEVEL"), 1, &MONKEY_GETOPT_set_string, (void *) loglev }
173
174
175/**
176 * Get number of verbose (-V) flags
177 *
178 * @param level where to store the verbosity level (should be an 'int')
179 */
180#define MONKEY_GETOPT_OPTION_VERBOSE(level) \
181 { 'V', "verbose", (const char *) NULL, gettext_noop("be verbose"), 0, &MONKEY_GETOPT_increment_value, (void *) level }
182
183
184/**
185 * Get configuration file name (-c option)
186 *
187 * @param fn set to the configuration file name
188 */
189#define MONKEY_GETOPT_OPTION_CFG_FILE(fn) \
190 { 'c', "config", "FILENAME", gettext_noop("use configuration file FILENAME"), 1, &MONKEY_GETOPT_set_string, (void *) fn }
191
192
193/**
194 * Marker for the end of the list of options.
195 */
196#define MONKEY_GETOPT_OPTION_END \
197 { '\0', NULL, NULL, NULL, 0, NULL, NULL }
198
199
200/**
201 * Parse the command line.
202 *
203 * @param binaryOptions Name of application with option summary
204 * @param allOptions defined options and handlers
205 * @param argc number of arguments
206 * @param argv actual arguments
207 * @return index into argv with first non-option
208 * argument, or MONKEY_SYSERR on error
209 */
210int
211MONKEY_GETOPT_run (const char *binaryOptions,
212 const struct MONKEY_GETOPT_CommandLineOption *allOptions,
213 unsigned int argc, char *const *argv);
214
215
216/**
217 * Set an option of type 'unsigned long long' from the command line.
218 * A pointer to this function should be passed as part of the
219 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
220 * of this type. It should be followed by a pointer to a value of
221 * type 'unsigned long long'.
222 *
223 * @param ctx command line processing context
224 * @param scls additional closure (will point to the 'unsigned long long')
225 * @param option name of the option
226 * @param value actual value of the option as a string.
227 * @return MONKEY_OK if parsing the value worked
228 */
229int
230MONKEY_GETOPT_set_ulong (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
231 void *scls, const char *option, const char *value);
232
233
234/**
235 * Set an option of type 'struct MONKEY_TIME_Relative' from the command line.
236 * A pointer to this function should be passed as part of the
237 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
238 * of this type. It should be followed by a pointer to a value of
239 * type 'struct MONKEY_TIME_Relative'.
240 *
241 * @param ctx command line processing context
242 * @param scls additional closure (will point to the 'struct MONKEY_TIME_Relative')
243 * @param option name of the option
244 * @param value actual value of the option as a string.
245 * @return MONKEY_OK if parsing the value worked
246 */
247int
248MONKEY_GETOPT_set_relative_time (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
249 void *scls, const char *option, const char *value);
250
251
252/**
253 * Set an option of type 'unsigned int' from the command line.
254 * A pointer to this function should be passed as part of the
255 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
256 * of this type. It should be followed by a pointer to a value of
257 * type 'unsigned int'.
258 *
259 * @param ctx command line processing context
260 * @param scls additional closure (will point to the 'unsigned int')
261 * @param option name of the option
262 * @param value actual value of the option as a string.
263 * @return MONKEY_OK if parsing the value worked
264 */
265int
266MONKEY_GETOPT_set_uint (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
267 void *scls, const char *option, const char *value);
268
269
270/**
271 * Set an option of type 'int' from the command line to 1 if the
272 * given option is present.
273 * A pointer to this function should be passed as part of the
274 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
275 * of this type. It should be followed by a pointer to a value of
276 * type 'int'.
277 *
278 * @param ctx command line processing context
279 * @param scls additional closure (will point to the 'int')
280 * @param option name of the option
281 * @param value not used (NULL)
282 * @return MONKEY_OK
283 */
284int
285MONKEY_GETOPT_set_one (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
286 void *scls, const char *option, const char *value);
287
288
289/**
290 * Set an option of type 'char *' from the command line.
291 * A pointer to this function should be passed as part of the
292 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
293 * of this type. It should be followed by a pointer to a value of
294 * type 'char *'.
295 *
296 * @param ctx command line processing context
297 * @param scls additional closure (will point to the 'char *',
298 * which will be allocated)
299 * @param option name of the option
300 * @param value actual value of the option (a string)
301 * @return MONKEY_OK
302 */
303int
304MONKEY_GETOPT_set_string (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
305 void *scls, const char *option, const char *value);
306
307/**
308 * Set an option of type 'unsigned int' from the command line. Each
309 * time the option flag is given, the value is incremented by one.
310 * A pointer to this function should be passed as part of the
311 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
312 * of this type. It should be followed by a pointer to a value of
313 * type 'int'.
314 *
315 * @param ctx command line processing context
316 * @param scls additional closure (will point to the 'int')
317 * @param option name of the option
318 * @param value not used (NULL)
319 * @return MONKEY_OK
320 */
321int
322MONKEY_GETOPT_increment_value (struct MONKEY_GETOPT_CommandLineProcessorContext
323 *ctx, void *scls, const char *option,
324 const char *value);
325
326
327/* *************** internal prototypes - use macros above! ************* */
328
329/**
330 * Print out details on command line options (implements --help).
331 *
332 * @param ctx command line processing context
333 * @param scls additional closure (points to about text)
334 * @param option name of the option
335 * @param value not used (NULL)
336 * @return MONKEY_SYSERR (do not continue)
337 */
338int
339MONKEY_GETOPT_format_help_ (struct MONKEY_GETOPT_CommandLineProcessorContext
340 *ctx, void *scls, const char *option,
341 const char *value);
342
343/**
344 * Print out program version (implements --version).
345 *
346 * @param ctx command line processing context
347 * @param scls additional closure (points to version string)
348 * @param option name of the option
349 * @param value not used (NULL)
350 * @return MONKEY_SYSERR (do not continue)
351 */
352int
353MONKEY_GETOPT_print_version_ (struct MONKEY_GETOPT_CommandLineProcessorContext
354 *ctx, void *scls, const char *option,
355 const char *value);
356
357#if 0 /* keep Emacsens' auto-indent happy */
358{
359#endif
360#ifdef __cplusplus
361}
362#endif
363
364
365/* ifndef MONKEY_GETOPT_LIB_H */
366#endif
367/* end of gnunet_getopt_lib.h */
diff --git a/pathologist/src/include/mxml.h b/pathologist/src/include/mxml.h
new file mode 100644
index 0000000..79c711f
--- /dev/null
+++ b/pathologist/src/include/mxml.h
@@ -0,0 +1,329 @@
1/*
2 * "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $"
3 *
4 * Header file for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2011 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 */
16
17/*
18 * Prevent multiple inclusion...
19 */
20
21#ifndef _mxml_h_
22# define _mxml_h_
23
24/*
25 * Include necessary headers...
26 */
27
28# include <stdio.h>
29# include <stdlib.h>
30# include <string.h>
31# include <ctype.h>
32# include <errno.h>
33
34
35/*
36 * Constants...
37 */
38
39# define MXML_TAB 8 /* Tabs every N columns */
40
41# define MXML_NO_CALLBACK 0 /* Don't use a type callback */
42# define MXML_INTEGER_CALLBACK mxml_integer_cb
43 /* Treat all data as integers */
44# define MXML_OPAQUE_CALLBACK mxml_opaque_cb
45 /* Treat all data as opaque */
46# define MXML_REAL_CALLBACK mxml_real_cb
47 /* Treat all data as real numbers */
48# define MXML_TEXT_CALLBACK 0 /* Treat all data as text */
49# define MXML_IGNORE_CALLBACK mxml_ignore_cb
50 /* Ignore all non-element content */
51
52# define MXML_NO_PARENT 0 /* No parent for the node */
53
54# define MXML_DESCEND 1 /* Descend when finding/walking */
55# define MXML_NO_DESCEND 0 /* Don't descend when finding/walking */
56# define MXML_DESCEND_FIRST -1 /* Descend for first find */
57
58# define MXML_WS_BEFORE_OPEN 0 /* Callback for before open tag */
59# define MXML_WS_AFTER_OPEN 1 /* Callback for after open tag */
60# define MXML_WS_BEFORE_CLOSE 2 /* Callback for before close tag */
61# define MXML_WS_AFTER_CLOSE 3 /* Callback for after close tag */
62
63# define MXML_ADD_BEFORE 0 /* Add node before specified node */
64# define MXML_ADD_AFTER 1 /* Add node after specified node */
65# define MXML_ADD_TO_PARENT NULL /* Add node relative to parent */
66
67
68/*
69 * Data types...
70 */
71
72typedef enum mxml_sax_event_e /**** SAX event type. ****/
73{
74 MXML_SAX_CDATA, /* CDATA node */
75 MXML_SAX_COMMENT, /* Comment node */
76 MXML_SAX_DATA, /* Data node */
77 MXML_SAX_DIRECTIVE, /* Processing directive node */
78 MXML_SAX_ELEMENT_CLOSE, /* Element closed */
79 MXML_SAX_ELEMENT_OPEN /* Element opened */
80} mxml_sax_event_t;
81
82typedef enum mxml_type_e /**** The XML node type. ****/
83{
84 MXML_IGNORE = -1, /* Ignore/throw away node @since Mini-XML 2.3@ */
85 MXML_ELEMENT, /* XML element with attributes */
86 MXML_INTEGER, /* Integer value */
87 MXML_OPAQUE, /* Opaque string */
88 MXML_REAL, /* Real value */
89 MXML_TEXT, /* Text fragment */
90 MXML_CUSTOM /* Custom data @since Mini-XML 2.1@ */
91} mxml_type_t;
92
93typedef void (*mxml_custom_destroy_cb_t)(void *);
94 /**** Custom data destructor ****/
95
96typedef void (*mxml_error_cb_t)(const char *);
97 /**** Error callback function ****/
98
99typedef struct mxml_attr_s /**** An XML element attribute value. @private@ ****/
100{
101 char *name; /* Attribute name */
102 char *value; /* Attribute value */
103} mxml_attr_t;
104
105typedef struct mxml_element_s /**** An XML element value. @private@ ****/
106{
107 char *name; /* Name of element */
108 int num_attrs; /* Number of attributes */
109 mxml_attr_t *attrs; /* Attributes */
110} mxml_element_t;
111
112typedef struct mxml_text_s /**** An XML text value. @private@ ****/
113{
114 int whitespace; /* Leading whitespace? */
115 char *string; /* Fragment string */
116} mxml_text_t;
117
118typedef struct mxml_custom_s /**** An XML custom value. @private@ ****/
119{
120 void *data; /* Pointer to (allocated) custom data */
121 mxml_custom_destroy_cb_t destroy; /* Pointer to destructor function */
122} mxml_custom_t;
123
124typedef union mxml_value_u /**** An XML node value. @private@ ****/
125{
126 mxml_element_t element; /* Element */
127 int integer; /* Integer number */
128 char *opaque; /* Opaque string */
129 double real; /* Real number */
130 mxml_text_t text; /* Text fragment */
131 mxml_custom_t custom; /* Custom data @since Mini-XML 2.1@ */
132} mxml_value_t;
133
134struct mxml_node_s /**** An XML node. @private@ ****/
135{
136 mxml_type_t type; /* Node type */
137 struct mxml_node_s *next; /* Next node under same parent */
138 struct mxml_node_s *prev; /* Previous node under same parent */
139 struct mxml_node_s *parent; /* Parent node */
140 struct mxml_node_s *child; /* First child node */
141 struct mxml_node_s *last_child; /* Last child node */
142 mxml_value_t value; /* Node value */
143 int ref_count; /* Use count */
144 void *user_data; /* User data */
145};
146
147typedef struct mxml_node_s mxml_node_t; /**** An XML node. ****/
148
149struct mxml_index_s /**** An XML node index. @private@ ****/
150{
151 char *attr; /* Attribute used for indexing or NULL */
152 int num_nodes; /* Number of nodes in index */
153 int alloc_nodes; /* Allocated nodes in index */
154 int cur_node; /* Current node */
155 mxml_node_t **nodes; /* Node array */
156};
157
158typedef struct mxml_index_s mxml_index_t;
159 /**** An XML node index. ****/
160
161typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
162 /**** Custom data load callback function ****/
163
164typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
165 /**** Custom data save callback function ****/
166
167typedef int (*mxml_entity_cb_t)(const char *);
168 /**** Entity callback function */
169
170typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
171 /**** Load callback function ****/
172
173typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
174 /**** Save callback function ****/
175
176typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
177 /**** SAX callback function ****/
178
179
180/*
181 * C++ support...
182 */
183
184# ifdef __cplusplus
185extern "C" {
186# endif /* __cplusplus */
187
188/*
189 * Prototypes...
190 */
191
192extern void mxmlAdd(mxml_node_t *parent, int where,
193 mxml_node_t *child, mxml_node_t *node);
194extern void mxmlDelete(mxml_node_t *node);
195extern void mxmlElementDeleteAttr(mxml_node_t *node,
196 const char *name);
197extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name);
198extern void mxmlElementSetAttr(mxml_node_t *node, const char *name,
199 const char *value);
200extern void mxmlElementSetAttrf(mxml_node_t *node, const char *name,
201 const char *format, ...)
202# ifdef __GNUC__
203__attribute__ ((__format__ (__printf__, 3, 4)))
204# endif /* __GNUC__ */
205;
206extern int mxmlEntityAddCallback(mxml_entity_cb_t cb);
207extern const char *mxmlEntityGetName(int val);
208extern int mxmlEntityGetValue(const char *name);
209extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb);
210extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
211 const char *name, const char *attr,
212 const char *value, int descend);
213extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path);
214extern const char *mxmlGetCDATA(mxml_node_t *node);
215extern const void *mxmlGetCustom(mxml_node_t *node);
216extern const char *mxmlGetElement(mxml_node_t *node);
217extern mxml_node_t *mxmlGetFirstChild(mxml_node_t *node);
218extern int mxmlGetInteger(mxml_node_t *node);
219extern mxml_node_t *mxmlGetLastChild(mxml_node_t *node);
220extern mxml_node_t *mxmlGetNextSibling(mxml_node_t *node);
221extern const char *mxmlGetOpaque(mxml_node_t *node);
222extern mxml_node_t *mxmlGetParent(mxml_node_t *node);
223extern mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node);
224extern double mxmlGetReal(mxml_node_t *node);
225extern int mxmlGetRefCount(mxml_node_t *node);
226extern const char *mxmlGetText(mxml_node_t *node, int *whitespace);
227extern mxml_type_t mxmlGetType(mxml_node_t *node);
228extern void *mxmlGetUserData(mxml_node_t *node);
229extern void mxmlIndexDelete(mxml_index_t *ind);
230extern mxml_node_t *mxmlIndexEnum(mxml_index_t *ind);
231extern mxml_node_t *mxmlIndexFind(mxml_index_t *ind,
232 const char *element,
233 const char *value);
234extern int mxmlIndexGetCount(mxml_index_t *ind);
235extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element,
236 const char *attr);
237extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
238extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, int fd,
239 mxml_type_t (*cb)(mxml_node_t *));
240extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp,
241 mxml_type_t (*cb)(mxml_node_t *));
242extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s,
243 mxml_type_t (*cb)(mxml_node_t *));
244extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
245extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data,
246 mxml_custom_destroy_cb_t destroy);
247extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
248extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, int integer);
249extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
250extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real);
251extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace,
252 const char *string);
253extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace,
254 const char *format, ...)
255# ifdef __GNUC__
256__attribute__ ((__format__ (__printf__, 3, 4)))
257# endif /* __GNUC__ */
258;
259extern mxml_node_t *mxmlNewXML(const char *version);
260extern int mxmlRelease(mxml_node_t *node);
261extern void mxmlRemove(mxml_node_t *node);
262extern int mxmlRetain(mxml_node_t *node);
263extern char *mxmlSaveAllocString(mxml_node_t *node,
264 mxml_save_cb_t cb);
265extern int mxmlSaveFd(mxml_node_t *node, int fd,
266 mxml_save_cb_t cb);
267extern int mxmlSaveFile(mxml_node_t *node, FILE *fp,
268 mxml_save_cb_t cb);
269extern int mxmlSaveString(mxml_node_t *node, char *buffer,
270 int bufsize, mxml_save_cb_t cb);
271extern mxml_node_t *mxmlSAXLoadFd(mxml_node_t *top, int fd,
272 mxml_type_t (*cb)(mxml_node_t *),
273 mxml_sax_cb_t sax, void *sax_data);
274extern mxml_node_t *mxmlSAXLoadFile(mxml_node_t *top, FILE *fp,
275 mxml_type_t (*cb)(mxml_node_t *),
276 mxml_sax_cb_t sax, void *sax_data);
277extern mxml_node_t *mxmlSAXLoadString(mxml_node_t *top, const char *s,
278 mxml_type_t (*cb)(mxml_node_t *),
279 mxml_sax_cb_t sax, void *sax_data);
280extern int mxmlSetCDATA(mxml_node_t *node, const char *data);
281extern int mxmlSetCustom(mxml_node_t *node, void *data,
282 mxml_custom_destroy_cb_t destroy);
283extern void mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
284 mxml_custom_save_cb_t save);
285extern int mxmlSetElement(mxml_node_t *node, const char *name);
286extern void mxmlSetErrorCallback(mxml_error_cb_t cb);
287extern int mxmlSetInteger(mxml_node_t *node, int integer);
288extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque);
289extern int mxmlSetReal(mxml_node_t *node, double real);
290extern int mxmlSetText(mxml_node_t *node, int whitespace,
291 const char *string);
292extern int mxmlSetTextf(mxml_node_t *node, int whitespace,
293 const char *format, ...)
294# ifdef __GNUC__
295__attribute__ ((__format__ (__printf__, 3, 4)))
296# endif /* __GNUC__ */
297;
298extern int mxmlSetUserData(mxml_node_t *node, void *data);
299extern void mxmlSetWrapMargin(int column);
300extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
301 int descend);
302extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
303 int descend);
304
305
306/*
307 * Semi-private functions...
308 */
309
310extern void mxml_error(const char *format, ...);
311extern mxml_type_t mxml_ignore_cb(mxml_node_t *node);
312extern mxml_type_t mxml_integer_cb(mxml_node_t *node);
313extern mxml_type_t mxml_opaque_cb(mxml_node_t *node);
314extern mxml_type_t mxml_real_cb(mxml_node_t *node);
315
316
317/*
318 * C++ support...
319 */
320
321# ifdef __cplusplus
322}
323# endif /* __cplusplus */
324#endif /* !_mxml_h_ */
325
326
327/*
328 * End of "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $".
329 */
diff --git a/pathologist/src/include/platform.h b/pathologist/src/include/platform.h
new file mode 100644
index 0000000..994a5b6
--- /dev/null
+++ b/pathologist/src/include/platform.h
@@ -0,0 +1,266 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file include/platform.h
23 * @brief plaform specifics
24 *
25 * @author Nils Durner
26 *
27 * This file should never be included by installed
28 * header files (thos starting with "gnunet_").
29 */
30
31#ifndef PLATFORM_H
32#define PLATFORM_H
33
34#ifndef HAVE_USED_CONFIG_H
35#define HAVE_USED_CONFIG_H
36#if HAVE_CONFIG_H
37//#include "gnunet_config.h"
38#endif
39#endif
40
41#ifdef WINDOWS
42#define BREAKPOINT asm("int $3;");
43#define GNUNET_SIGCHLD 17
44#else
45#define BREAKPOINT
46#define GNUNET_SIGCHLD SIGCHLD
47#endif
48
49#ifdef HAVE_SYS_TYPES_H
50#include <sys/types.h>
51#endif
52
53#define ALLOW_EXTRA_CHECKS GNUNET_NO
54
55/**
56 * For strptime (glibc2 needs this).
57 */
58#ifndef _XOPEN_SOURCE
59#define _XOPEN_SOURCE
60#endif
61
62#ifndef _REENTRANT
63#define _REENTRANT
64#endif
65
66/* configuration options */
67
68#define VERBOSE_STATS 0
69
70#ifdef CYGWIN
71#include <sys/reent.h>
72#endif
73
74#ifdef _MSC_VER
75#ifndef FD_SETSIZE
76#define FD_SETSIZE 1024
77#endif
78#include <Winsock2.h>
79#include <ws2tcpip.h>
80#else
81#ifndef MINGW
82#include <netdb.h>
83#include <sys/socket.h>
84#include <sys/un.h>
85#if HAVE_NETINET_IN_H
86#include <netinet/in.h>
87#endif
88#if HAVE_NETINET_IN_SYSTM_H
89#include <netinet/in_systm.h>
90#endif
91#include <netinet/ip.h> /* superset of previous */
92#include <arpa/inet.h>
93#include <netinet/tcp.h>
94#include <pwd.h>
95#include <sys/ioctl.h>
96#include <sys/wait.h>
97#include <grp.h>
98#else
99#include "winproc.h"
100#endif
101#endif
102
103#include <string.h>
104#include <stdio.h>
105#include <stdlib.h>
106#include <stdint.h>
107#include <stdarg.h>
108#include <errno.h>
109#include <signal.h>
110#include <libgen.h>
111#ifdef WINDOWS
112#include <malloc.h> /* for alloca(), on other OSes it's in stdlib.h */
113#endif
114#ifndef _MSC_VER
115#include <unistd.h> /* KLB_FIX */
116#endif
117#include <sys/stat.h>
118#include <sys/types.h>
119#ifndef _MSC_VER
120#include <dirent.h> /* KLB_FIX */
121#endif
122#include <fcntl.h>
123#include <math.h>
124#if HAVE_SYS_PARAM_H
125#include <sys/param.h>
126#endif
127#if TIME_WITH_SYS_TIME
128#include <sys/time.h>
129#include <time.h>
130#else
131#if HAVE_SYS_TIME_H
132#include <sys/time.h>
133#else
134#include <time.h>
135#endif
136#endif
137
138#ifdef SOMEBSD
139#include <net/if.h>
140#endif
141#ifdef GNUNET_freeBSD
142#include <semaphore.h>
143#endif
144#ifdef DARWIN
145#include <dlfcn.h>
146#include <semaphore.h>
147#include <net/if.h>
148#endif
149#if defined(LINUX) || defined(GNU)
150#include <net/if.h>
151#endif
152#ifdef SOLARIS
153#include <sys/sockio.h>
154#include <sys/filio.h>
155#include <sys/loadavg.h>
156#include <semaphore.h>
157#endif
158#if HAVE_UCRED_H
159#include <ucred.h>
160#endif
161#ifdef CYGWIN
162#include <windows.h>
163#include <cygwin/if.h>
164#endif
165#if HAVE_IFADDRS_H
166#include <ifaddrs.h>
167#endif
168#include <errno.h>
169#include <limits.h>
170
171#if HAVE_VFORK_H
172#include <vfork.h>
173#endif
174
175#include <ctype.h>
176#if HAVE_SYS_RESOURCE_H
177#include <sys/resource.h>
178#endif
179
180#if HAVE_ENDIAN_H
181#include <endian.h>
182#endif
183#if HAVE_SYS_ENDIAN_H
184#include <sys/endian.h>
185#endif
186
187#include "plibc.h"
188
189//#include <locale.h>
190//#ifndef FRAMEWORK_BUILD
191//#include "gettext.h"
192///**
193// * GNU gettext support macro.
194// */
195//#define _(String) dgettext("gnunet",String)
196//#define LIBEXTRACTOR_GETTEXT_DOMAIN "libextractor"
197//#else
198//#include "libintlemu.h"
199//#define _(String) dgettext("org.gnunet.gnunet",String)
200//#define LIBEXTRACTOR_GETTEXT_DOMAIN "org.gnunet.libextractor"
201//#endif
202
203#ifdef CYGWIN
204#define SIOCGIFCONF _IOW('s', 100, struct ifconf) /* get if list */
205#define SIOCGIFFLAGS _IOW('s', 101, struct ifreq) /* Get if flags */
206#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
207#endif
208
209#ifndef MINGW
210#include <sys/mman.h>
211#endif
212
213#ifdef FREEBSD
214#define __BYTE_ORDER BYTE_ORDER
215#define __BIG_ENDIAN BIG_ENDIAN
216#endif
217
218#ifdef DARWIN
219#define __BYTE_ORDER BYTE_ORDER
220#define __BIG_ENDIAN BIG_ENDIAN
221 /* not available on darwin, override configure */
222#undef HAVE_STAT64
223#undef HAVE_MREMAP
224#endif
225
226
227#if !HAVE_ATOLL
228long long
229atoll (const char *nptr);
230#endif
231
232#if ENABLE_NLS
233#include "langinfo.h"
234#endif
235
236#ifndef SIZE_MAX
237#define SIZE_MAX ((size_t)(-1))
238#endif
239
240#ifndef O_LARGEFILE
241#define O_LARGEFILE 0
242#endif
243
244/**
245 * AI_NUMERICSERV not defined in windows. Then we just do without.
246 */
247#ifndef AI_NUMERICSERV
248#define AI_NUMERICSERV 0
249#endif
250
251
252#if defined(__sparc__)
253#define MAKE_UNALIGNED(val) ({ __typeof__((val)) __tmp; memmove(&__tmp, &(val), sizeof((val))); __tmp; })
254#else
255#define MAKE_UNALIGNED(val) val
256#endif
257
258#if WINDOWS
259#define FDTYPE HANDLE
260#define SOCKTYPE SOCKET
261#else
262#define FDTYPE int
263#define SOCKTYPE int
264#endif
265
266#endif
diff --git a/pathologist/src/include/plibc.h b/pathologist/src/include/plibc.h
new file mode 100644
index 0000000..8314f21
--- /dev/null
+++ b/pathologist/src/include/plibc.h
@@ -0,0 +1,810 @@
1/*
2 This file is part of PlibC.
3 (C) 2005, 2006, 2007, 2008, 2009, 2010 Nils Durner (and other contributing authors)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20/**
21 * @file include/plibc.h
22 * @brief PlibC header
23 * @attention This file is usually not installed under Unix,
24 * so ship it with your application
25 * @version $Revision: 69 $
26 */
27
28#ifndef _PLIBC_H_
29#define _PLIBC_H_
30
31#ifndef SIGALRM
32#define SIGALRM 14
33#endif
34
35#ifdef __cplusplus
36extern "C"
37{
38#endif
39
40#include <stddef.h>
41
42#ifdef Q_OS_WIN32
43#define WINDOWS 1
44#endif
45
46#define HAVE_PLIBC_FD 0
47
48#ifdef WINDOWS
49
50#if ENABLE_NLS
51#include "langinfo.h"
52#endif
53
54#include <winsock2.h>
55#include <ws2tcpip.h>
56#include <windows.h>
57#include <sys/types.h>
58#include <time.h>
59#include <stdio.h>
60#include <sys/types.h>
61#include <sys/stat.h>
62#include <dirent.h>
63#include <errno.h>
64#include <stdarg.h>
65
66#define __BYTE_ORDER BYTE_ORDER
67#define __BIG_ENDIAN BIG_ENDIAN
68
69/* Conflicts with our definitions */
70#define __G_WIN32_H__
71
72/* Convert LARGE_INTEGER to double */
73#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + \
74 (double)((x).LowPart))
75
76 struct stat64
77 {
78 _dev_t st_dev;
79 _ino_t st_ino;
80 _mode_t st_mode;
81 short st_nlink;
82 short st_uid;
83 short st_gid;
84 _dev_t st_rdev;
85 __int64 st_size;
86 __time64_t st_atime;
87 __time64_t st_mtime;
88 __time64_t st_ctime;
89 };
90
91 typedef unsigned int sa_family_t;
92
93 struct sockaddr_un
94 {
95 short sun_family; /*AF_UNIX */
96 char sun_path[108]; /*path name */
97 };
98
99#ifndef pid_t
100#define pid_t DWORD
101#endif
102
103#ifndef error_t
104#define error_t int
105#endif
106
107#ifndef WEXITSTATUS
108#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
109#endif
110
111#ifndef MSG_DONTWAIT
112#define MSG_DONTWAIT 0
113#endif
114
115 enum
116 {
117 _SC_PAGESIZE = 30,
118 _SC_PAGE_SIZE = 30
119 };
120
121/* Thanks to the Cygwin project */
122#define ENOCSI 43 /* No CSI structure available */
123#define EL2HLT 44 /* Level 2 halted */
124#ifndef EDEADLK
125#define EDEADLK 45 /* Deadlock condition */
126#endif
127#ifndef ENOLCK
128#define ENOLCK 46 /* No record locks available */
129#endif
130#define EBADE 50 /* Invalid exchange */
131#define EBADR 51 /* Invalid request descriptor */
132#define EXFULL 52 /* Exchange full */
133#define ENOANO 53 /* No anode */
134#define EBADRQC 54 /* Invalid request code */
135#define EBADSLT 55 /* Invalid slot */
136#ifndef EDEADLOCK
137#define EDEADLOCK EDEADLK /* File locking deadlock error */
138#endif
139#define EBFONT 57 /* Bad font file fmt */
140#define ENOSTR 60 /* Device not a stream */
141#define ENODATA 61 /* No data (for no delay io) */
142#define ETIME 62 /* Timer expired */
143#define ENOSR 63 /* Out of streams resources */
144#define ENONET 64 /* Machine is not on the network */
145#define ENOPKG 65 /* Package not installed */
146#define EREMOTE 66 /* The object is remote */
147#define ENOLINK 67 /* The link has been severed */
148#define EADV 68 /* Advertise error */
149#define ESRMNT 69 /* Srmount error */
150#define ECOMM 70 /* Communication error on send */
151#define EPROTO 71 /* Protocol error */
152#define EMULTIHOP 74 /* Multihop attempted */
153#define ELBIN 75 /* Inode is remote (not really error) */
154#define EDOTDOT 76 /* Cross mount point (not really error) */
155#define EBADMSG 77 /* Trying to read unreadable message */
156#define ENOTUNIQ 80 /* Given log. name not unique */
157#define EBADFD 81 /* f.d. invalid for this operation */
158#define EREMCHG 82 /* Remote address changed */
159#define ELIBACC 83 /* Can't access a needed shared lib */
160#define ELIBBAD 84 /* Accessing a corrupted shared lib */
161#define ELIBSCN 85 /* .lib section in a.out corrupted */
162#define ELIBMAX 86 /* Attempting to link in too many libs */
163#define ELIBEXEC 87 /* Attempting to exec a shared library */
164#ifndef ENOSYS
165#define ENOSYS 88 /* Function not implemented */
166#endif
167#define ENMFILE 89 /* No more files */
168#ifndef ENOTEMPTY
169#define ENOTEMPTY 90 /* Directory not empty */
170#endif
171#ifndef ENAMETOOLONG
172#define ENAMETOOLONG 91 /* File or path name too long */
173#endif
174#define ELOOP 92 /* Too many symbolic links */
175#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
176#define EPFNOSUPPORT 96 /* Protocol family not supported */
177#define ECONNRESET 104 /* Connection reset by peer */
178#define ENOBUFS 105 /* No buffer space available */
179#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
180#define EPROTOTYPE 107 /* Protocol wrong type for socket */
181#define ENOTSOCK 108 /* Socket operation on non-socket */
182#define ENOPROTOOPT 109 /* Protocol not available */
183#define ESHUTDOWN 110 /* Can't send after socket shutdown */
184#define ECONNREFUSED 111 /* Connection refused */
185#define EADDRINUSE 112 /* Address already in use */
186#define ECONNABORTED 113 /* Connection aborted */
187#define ENETUNREACH 114 /* Network is unreachable */
188#define ENETDOWN 115 /* Network interface is not configured */
189#ifndef ETIMEDOUT
190#define ETIMEDOUT 116 /* Connection timed out */
191#endif
192#define EHOSTDOWN 117 /* Host is down */
193#define EHOSTUNREACH 118 /* Host is unreachable */
194#define EINPROGRESS 119 /* Connection already in progress */
195#define EALREADY 120 /* Socket already connected */
196#define EDESTADDRREQ 121 /* Destination address required */
197#define EMSGSIZE 122 /* Message too long */
198#define EPROTONOSUPPORT 123 /* Unknown protocol */
199#define ESOCKTNOSUPPORT 124 /* Socket type not supported */
200#define EADDRNOTAVAIL 125 /* Address not available */
201#define ENETRESET 126 /* Connection aborted by network */
202#define EISCONN 127 /* Socket is already connected */
203#define ENOTCONN 128 /* Socket is not connected */
204#define ETOOMANYREFS 129 /* Too many references: cannot splice */
205#define EPROCLIM 130 /* Too many processes */
206#define EUSERS 131 /* Too many users */
207#define EDQUOT 132 /* Disk quota exceeded */
208#define ESTALE 133 /* Unknown error */
209#ifndef ENOTSUP
210#define ENOTSUP 134 /* Not supported */
211#endif
212#define ENOMEDIUM 135 /* No medium (in tape drive) */
213#define ENOSHARE 136 /* No such host or network path */
214#define ECASECLASH 137 /* Filename exists with different case */
215#define EWOULDBLOCK EAGAIN /* Operation would block */
216#define EOVERFLOW 139 /* Value too large for defined data type */
217
218#undef HOST_NOT_FOUND
219#define HOST_NOT_FOUND 1
220#undef TRY_AGAIN
221#define TRY_AGAIN 2
222#undef NO_RECOVERY
223#define NO_RECOVERY 3
224#undef NO_ADDRESS
225#define NO_ADDRESS 4
226
227#define PROT_READ 0x1
228#define PROT_WRITE 0x2
229#define MAP_SHARED 0x1
230#define MAP_PRIVATE 0x2 /* unsupported */
231#define MAP_FIXED 0x10
232#define MAP_FAILED ((void *)-1)
233
234 struct statfs
235 {
236 long f_type; /* type of filesystem (see below) */
237 long f_bsize; /* optimal transfer block size */
238 long f_blocks; /* total data blocks in file system */
239 long f_bfree; /* free blocks in fs */
240 long f_bavail; /* free blocks avail to non-superuser */
241 long f_files; /* total file nodes in file system */
242 long f_ffree; /* free file nodes in fs */
243 long f_fsid; /* file system id */
244 long f_namelen; /* maximum length of filenames */
245 long f_spare[6]; /* spare for later */
246 };
247
248 extern const struct in6_addr in6addr_any; /* :: */
249 extern const struct in6_addr in6addr_loopback; /* ::1 */
250
251/* Taken from the Wine project <http://www.winehq.org>
252 /wine/include/winternl.h */
253 enum SYSTEM_INFORMATION_CLASS
254 {
255 SystemBasicInformation = 0,
256 Unknown1,
257 SystemPerformanceInformation = 2,
258 SystemTimeOfDayInformation = 3, /* was SystemTimeInformation */
259 Unknown4,
260 SystemProcessInformation = 5,
261 Unknown6,
262 Unknown7,
263 SystemProcessorPerformanceInformation = 8,
264 Unknown9,
265 Unknown10,
266 SystemDriverInformation,
267 Unknown12,
268 Unknown13,
269 Unknown14,
270 Unknown15,
271 SystemHandleList,
272 Unknown17,
273 Unknown18,
274 Unknown19,
275 Unknown20,
276 SystemCacheInformation,
277 Unknown22,
278 SystemInterruptInformation = 23,
279 SystemExceptionInformation = 33,
280 SystemRegistryQuotaInformation = 37,
281 SystemLookasideInformation = 45
282 };
283
284 typedef struct
285 {
286 LARGE_INTEGER IdleTime;
287 LARGE_INTEGER KernelTime;
288 LARGE_INTEGER UserTime;
289 LARGE_INTEGER Reserved1[2];
290 ULONG Reserved2;
291 } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
292
293#define sleep(secs) (Sleep(secs * 1000))
294
295/*********************** statfs *****************************/
296/* fake block size */
297#define FAKED_BLOCK_SIZE 512
298
299/* linux-compatible values for fs type */
300#define MSDOS_SUPER_MAGIC 0x4d44
301#define NTFS_SUPER_MAGIC 0x5346544E
302
303/*********************** End of statfs ***********************/
304
305#define SHUT_RDWR SD_BOTH
306
307/* Operations for flock() */
308#define LOCK_SH 1 /* shared lock */
309#define LOCK_EX 2 /* exclusive lock */
310#define LOCK_NB 4 /* or'd with one of the above to prevent
311 * blocking */
312#define LOCK_UN 8 /* remove lock */
313
314/* Not supported under MinGW */
315#define S_IRGRP 0
316#define S_IWGRP 0
317#define S_IROTH 0
318#define S_IXGRP 0
319#define S_IWOTH 0
320#define S_IXOTH 0
321#define S_ISUID 0
322#define S_ISGID 0
323#define S_ISVTX 0
324#define S_IRWXG 0
325#define S_IRWXO 0
326
327#define SHUT_WR SD_SEND
328#define SHUT_RD SD_RECEIVE
329#define SHUT_RDWR SD_BOTH
330
331#define SIGKILL 9
332#define SIGTERM 15
333
334#define SetErrnoFromWinError(e) _SetErrnoFromWinError(e, __FILE__, __LINE__)
335
336 BOOL _plibc_CreateShortcut (const char *pszSrc, const char *pszDest);
337 BOOL _plibc_DereferenceShortcut (char *pszShortcut);
338 char *plibc_ChooseDir (char *pszTitle, unsigned long ulFlags);
339 char *plibc_ChooseFile (char *pszTitle, unsigned long ulFlags);
340 long QueryRegistry (HKEY hMainKey, const char *pszKey, const char *pszSubKey,
341 char *pszBuffer, long *pdLength);
342
343 BOOL __win_IsHandleMarkedAsBlocking (int hHandle);
344 void __win_SetHandleBlockingMode (int s, BOOL bBlocking);
345 void __win_DiscardHandleBlockingMode (int s);
346 int _win_isSocketValid (int s);
347 int plibc_conv_to_win_path (const char *pszUnix, char *pszWindows);
348 unsigned plibc_get_handle_count ();
349
350 typedef void (*TPanicProc) (int, char *);
351 void plibc_set_panic_proc (TPanicProc proc);
352
353 int flock (int fd, int operation);
354 int fsync (int fildes);
355 int inet_pton (int af, const char *src, void *dst);
356 int inet_pton4 (const char *src, u_char * dst, int pton);
357#if USE_IPV6
358 int inet_pton6 (const char *src, u_char * dst);
359#endif
360 int truncate (const char *fname, int distance);
361 int statfs (const char *path, struct statfs *buf);
362 const char *hstrerror (int err);
363 int mkstemp (char *tmplate);
364 char *strptime (const char *buf, const char *format, struct tm *tm);
365 const char *inet_ntop (int af, const void *src, char *dst, size_t size);
366
367 int plibc_init (char *pszOrg, char *pszApp);
368 void plibc_shutdown ();
369 int plibc_initialized ();
370 int plibc_conv_to_win_path_ex (const char *pszUnix, char *pszWindows,
371 int derefLinks);
372 void _SetErrnoFromWinError (long lWinError, char *pszCaller, int iLine);
373 void SetErrnoFromWinsockError (long lWinError);
374 void SetHErrnoFromWinError (long lWinError);
375 void SetErrnoFromHRESULT (HRESULT hRes);
376 int GetErrnoFromWinsockError (long lWinError);
377 FILE *_win_fopen (const char *filename, const char *mode);
378 DIR *_win_opendir (const char *dirname);
379 int _win_open (const char *filename, int oflag, ...);
380#ifdef ENABLE_NLS
381 char *_win_bindtextdomain (const char *domainname, const char *dirname);
382#endif
383 int _win_chdir (const char *path);
384 int _win_close (int fd);
385 int _win_creat (const char *path, mode_t mode);
386 char *_win_ctime (const time_t * clock);
387 char *_win_ctime_r (const time_t * clock, char *buf);
388 int _win_fstat (int handle, struct stat *buffer);
389 int _win_ftruncate (int fildes, off_t length);
390 void _win_gettimeofday (struct timeval *tp, void *tzp);
391 int _win_kill (pid_t pid, int sig);
392 int _win_pipe (int *phandles);
393 int _win_rmdir (const char *path);
394 int _win_access (const char *path, int mode);
395 int _win_chmod (const char *filename, int pmode);
396 char *realpath (const char *file_name, char *resolved_name);
397 long _win_random (void);
398 void _win_srandom (unsigned int seed);
399 int _win_remove (const char *path);
400 int _win_rename (const char *oldname, const char *newname);
401 int _win_stat (const char *path, struct stat *buffer);
402 int _win_stat64 (const char *path, struct stat64 *buffer);
403 long _win_sysconf (int name);
404 int _win_unlink (const char *filename);
405 int _win_write (int fildes, const void *buf, size_t nbyte);
406 int _win_read (int fildes, void *buf, size_t nbyte);
407 size_t _win_fwrite (const void *buffer, size_t size, size_t count,
408 FILE * stream);
409 size_t _win_fread (void *buffer, size_t size, size_t count, FILE * stream);
410 int _win_symlink (const char *path1, const char *path2);
411 void *_win_mmap (void *start, size_t len, int access, int flags, int fd,
412 unsigned long long offset);
413 int _win_munmap (void *start, size_t length);
414 int _win_lstat (const char *path, struct stat *buf);
415 int _win_lstat64 (const char *path, struct stat64 *buf);
416 int _win_readlink (const char *path, char *buf, size_t bufsize);
417 int _win_accept (int s, struct sockaddr *addr, int *addrlen);
418 int _win_printf (const char *format, ...);
419 int _win_fprintf (FILE * f, const char *format, ...);
420 int _win_vprintf (const char *format, va_list ap);
421 int _win_vfprintf (FILE * stream, const char *format, va_list arg_ptr);
422 int _win_vsprintf (char *dest, const char *format, va_list arg_ptr);
423 int _win_vsnprintf (char *str, size_t size, const char *format,
424 va_list arg_ptr);
425 int _win_snprintf (char *str, size_t size, const char *format, ...);
426 int _win_sprintf (char *dest, const char *format, ...);
427 int _win_vsscanf (const char *str, const char *format, va_list arg_ptr);
428 int _win_sscanf (const char *str, const char *format, ...);
429 int _win_vfscanf (FILE * stream, const char *format, va_list arg_ptr);
430 int _win_vscanf (const char *format, va_list arg_ptr);
431 int _win_scanf (const char *format, ...);
432 int _win_fscanf (FILE * stream, const char *format, ...);
433 pid_t _win_waitpid (pid_t pid, int *stat_loc, int options);
434 int _win_bind (int s, const struct sockaddr *name, int namelen);
435 int _win_connect (int s, const struct sockaddr *name, int namelen);
436 int _win_getpeername (int s, struct sockaddr *name, int *namelen);
437 int _win_getsockname (int s, struct sockaddr *name, int *namelen);
438 int _win_getsockopt (int s, int level, int optname, char *optval,
439 int *optlen);
440 int _win_listen (int s, int backlog);
441 int _win_recv (int s, char *buf, int len, int flags);
442 int _win_recvfrom (int s, void *buf, int len, int flags,
443 struct sockaddr *from, int *fromlen);
444 int _win_select (int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds,
445 const struct timeval *tv);
446 int _win_send (int s, const char *buf, int len, int flags);
447 int _win_sendto (int s, const char *buf, int len, int flags,
448 const struct sockaddr *to, int tolen);
449 int _win_setsockopt (int s, int level, int optname, const void *optval,
450 int optlen);
451 int _win_shutdown (int s, int how);
452 int _win_socket (int af, int type, int protocol);
453 struct hostent *_win_gethostbyaddr (const char *addr, int len, int type);
454 struct hostent *_win_gethostbyname (const char *name);
455 struct hostent *gethostbyname2 (const char *name, int af);
456 char *_win_strerror (int errnum);
457 int IsWinNT ();
458 char *index (const char *s, int c);
459
460#if !HAVE_STRNDUP
461 char *strndup (const char *s, size_t n);
462#endif
463#if !HAVE_STRNLEN
464 size_t strnlen (const char *str, size_t maxlen);
465#endif
466 char *stpcpy (char *dest, const char *src);
467 char *strcasestr (const char *haystack_start, const char *needle_start);
468
469#define strcasecmp(a, b) stricmp(a, b)
470#define strncasecmp(a, b, c) strnicmp(a, b, c)
471
472#endif /* WINDOWS */
473
474#ifndef WINDOWS
475#define DIR_SEPARATOR '/'
476#define DIR_SEPARATOR_STR "/"
477#define PATH_SEPARATOR ':'
478#define PATH_SEPARATOR_STR ":"
479#define NEWLINE "\n"
480
481#ifdef ENABLE_NLS
482#define BINDTEXTDOMAIN(d, n) bindtextdomain(d, n)
483#endif
484#define CREAT(p, m) creat(p, m)
485#define PLIBC_CTIME(c) ctime(c)
486#define CTIME_R(c, b) ctime_r(c, b)
487#undef FOPEN
488#define FOPEN(f, m) fopen(f, m)
489#define FTRUNCATE(f, l) ftruncate(f, l)
490#define OPENDIR(d) opendir(d)
491#define OPEN open
492#define CHDIR(d) chdir(d)
493#define CLOSE(f) close(f)
494#define LSEEK(f, o, w) lseek(f, o, w)
495#define RMDIR(f) rmdir(f)
496#define ACCESS(p, m) access(p, m)
497#define CHMOD(f, p) chmod(f, p)
498#define FSTAT(h, b) fstat(h, b)
499#define PLIBC_KILL(p, s) kill(p, s)
500#define PIPE(h) pipe(h)
501#define REMOVE(p) remove(p)
502#define RENAME(o, n) rename(o, n)
503#define STAT(p, b) stat(p, b)
504#define STAT64(p, b) stat64(p, b)
505#define SYSCONF(n) sysconf(n)
506#define UNLINK(f) unlink(f)
507#define WRITE(f, b, n) write(f, b, n)
508#define READ(f, b, n) read(f, b, n)
509#define GN_FREAD(b, s, c, f) fread(b, s, c, f)
510#define GN_FWRITE(b, s, c, f) fwrite(b, s, c, f)
511#define SYMLINK(a, b) symlink(a, b)
512#define MMAP(s, l, p, f, d, o) mmap(s, l, p, f, d, o)
513#define MUNMAP(s, l) munmap(s, l)
514#define STRERROR(i) strerror(i)
515#define RANDOM() random()
516#define SRANDOM(s) srandom(s)
517#define READLINK(p, b, s) readlink(p, b, s)
518#define LSTAT(p, b) lstat(p, b)
519#define LSTAT64(p, b) lstat64(p, b)
520#define PRINTF printf
521#define FPRINTF fprintf
522#define VPRINTF(f, a) vprintf(f, a)
523#define VFPRINTF(s, f, a) vfprintf(s, f, a)
524#define VSPRINTF(d, f, a) vsprintf(d, f, a)
525#define VSNPRINTF(str, size, fmt, a) vsnprintf(str, size, fmt, a)
526#define _REAL_SNPRINTF snprintf
527#define SPRINTF sprintf
528#define VSSCANF(s, f, a) vsscanf(s, f, a)
529#define SSCANF sscanf
530#define VFSCANF(s, f, a) vfscanf(s, f, a)
531#define VSCANF(f, a) vscanf(f, a)
532#define SCANF scanf
533#define FSCANF fscanf
534#define WAITPID(p, s, o) waitpid(p, s, o)
535#define ACCEPT(s, a, l) accept(s, a, l)
536#define BIND(s, n, l) bind(s, n, l)
537#define CONNECT(s, n, l) connect(s, n, l)
538#define GETPEERNAME(s, n, l) getpeername(s, n, l)
539#define GETSOCKNAME(s, n, l) getsockname(s, n, l)
540#define GETSOCKOPT(s, l, o, v, p) getsockopt(s, l, o, v, p)
541#define LISTEN(s, b) listen(s, b)
542#define RECV(s, b, l, f) recv(s, b, l, f)
543#define RECVFROM(s, b, l, f, r, o) recvfrom(s, b, l, f, r, o)
544#define SELECT(n, r, w, e, t) select(n, r, w, e, t)
545#define SEND(s, b, l, f) send(s, b, l, f)
546#define SENDTO(s, b, l, f, o, n) sendto(s, b, l, f, o, n)
547#define SETSOCKOPT(s, l, o, v, n) setsockopt(s, l, o, v, n)
548#define SHUTDOWN(s, h) shutdown(s, h)
549#define SOCKET(a, t, p) socket(a, t, p)
550#define GETHOSTBYADDR(a, l, t) gethostbyname(a, l, t)
551#define GETHOSTBYNAME(n) gethostbyname(n)
552#define GETTIMEOFDAY(t, n) gettimeofday(t, n)
553#define INSQUE(e, p) insque(e, p)
554#define REMQUE(e) remque(e)
555#define HSEARCH(i, a) hsearch(i, a)
556#define HCREATE(n) hcreate(n)
557#define HDESTROY() hdestroy()
558#define HSEARCH_R(i, a, r, h) hsearch_r(i, a, r, h)
559#define HCREATE_R(n, h) hcreate_r(n, h)
560#define HDESTROY_R(h) hdestroy_r(h)
561#define TSEARCH(k, r, c) tsearch(k, r, c)
562#define TFIND(k, r, c) tfind(k, r, c)
563#define TDELETE(k, r, c) tdelete(k, r, c)
564#define TWALK(r, a) twalk(r, a)
565#define TDESTROY(r, f) tdestroy(r, f)
566#define LFIND(k, b, n, s, c) lfind(k, b, n, s, c)
567#define LSEARCH(k, b, n, s, c) lsearch(k, b, n, s, c)
568#else
569#define DIR_SEPARATOR '\\'
570#define DIR_SEPARATOR_STR "\\"
571#define PATH_SEPARATOR ';'
572#define PATH_SEPARATOR_STR ";"
573#define NEWLINE "\r\n"
574
575#ifdef ENABLE_NLS
576#define BINDTEXTDOMAIN(d, n) _win_bindtextdomain(d, n)
577#endif
578#define CREAT(p, m) _win_creat(p, m)
579#define PLIBC_CTIME(c) _win_ctime(c)
580#define CTIME_R(c, b) _win_ctime_r(c, b)
581#define FOPEN(f, m) _win_fopen(f, m)
582#define FTRUNCATE(f, l) _win_ftruncate(f, l)
583#define OPENDIR(d) _win_opendir(d)
584#define OPEN _win_open
585#define CHDIR(d) _win_chdir(d)
586#define CLOSE(f) _win_close(f)
587#define PLIBC_KILL(p, s) _win_kill(p, s)
588#define LSEEK(f, o, w) _win_lseek(f, o, w)
589#define FSTAT(h, b) _win_fstat(h, b)
590#define RMDIR(f) _win_rmdir(f)
591#define ACCESS(p, m) _win_access(p, m)
592#define CHMOD(f, p) _win_chmod(f, p)
593#define PIPE(h) _win_pipe(h)
594#define RANDOM() _win_random()
595#define SRANDOM(s) _win_srandom(s)
596#define REMOVE(p) _win_remove(p)
597#define RENAME(o, n) _win_rename(o, n)
598#define STAT(p, b) _win_stat(p, b)
599#define STAT64(p, b) _win_stat64(p, b)
600#define SYSCONF(n) _win_sysconf(n)
601#define UNLINK(f) _win_unlink(f)
602#define WRITE(f, b, n) _win_write(f, b, n)
603#define READ(f, b, n) _win_read(f, b, n)
604#define GN_FREAD(b, s, c, f) _win_fread(b, s, c, f)
605#define GN_FWRITE(b, s, c, f) _win_fwrite(b, s, c, f)
606#define SYMLINK(a, b) _win_symlink(a, b)
607#define MMAP(s, l, p, f, d, o) _win_mmap(s, l, p, f, d, o)
608#define MUNMAP(s, l) _win_munmap(s, l)
609#define STRERROR(i) _win_strerror(i)
610#define READLINK(p, b, s) _win_readlink(p, b, s)
611#define LSTAT(p, b) _win_lstat(p, b)
612#define LSTAT64(p, b) _win_lstat64(p, b)
613#define PRINTF(f, ...) _win_printf(f , __VA_ARGS__)
614#define FPRINTF(fil, fmt, ...) _win_fprintf(fil, fmt, __VA_ARGS__)
615#define VPRINTF(f, a) _win_vprintf(f, a)
616#define VFPRINTF(s, f, a) _win_vfprintf(s, f, a)
617#define VSPRINTF(d, f, a) _win_vsprintf(d, f, a)
618#define VSNPRINTF(str, size, fmt, a) _win_vsnprintf(str, size, fmt, a)
619#define _REAL_SNPRINTF(str, size, fmt, ...) _win_snprintf(str, size, fmt, __VA_ARGS__)
620#define SPRINTF(d, f, ...) _win_sprintf(d, f, __VA_ARGS__)
621#define VSSCANF(s, f, a) _win_vsscanf(s, f, a)
622#define SSCANF(s, f, ...) _win_sscanf(s, f, __VA_ARGS__)
623#define VFSCANF(s, f, a) _win_vfscanf(s, f, a)
624#define VSCANF(f, a) _win_vscanf(f, a)
625#define SCANF(f, ...) _win_scanf(f, __VA_ARGS__)
626#define FSCANF(s, f, ...) _win_fscanf(s, f, __VA_ARGS__)
627#define WAITPID(p, s, o) _win_waitpid(p, s, o)
628#define ACCEPT(s, a, l) _win_accept(s, a, l)
629#define BIND(s, n, l) _win_bind(s, n, l)
630#define CONNECT(s, n, l) _win_connect(s, n, l)
631#define GETPEERNAME(s, n, l) _win_getpeername(s, n, l)
632#define GETSOCKNAME(s, n, l) _win_getsockname(s, n, l)
633#define GETSOCKOPT(s, l, o, v, p) _win_getsockopt(s, l, o, v, p)
634#define LISTEN(s, b) _win_listen(s, b)
635#define RECV(s, b, l, f) _win_recv(s, b, l, f)
636#define RECVFROM(s, b, l, f, r, o) _win_recvfrom(s, b, l, f, r, o)
637#define SELECT(n, r, w, e, t) _win_select(n, r, w, e, t)
638#define SEND(s, b, l, f) _win_send(s, b, l, f)
639#define SENDTO(s, b, l, f, o, n) _win_sendto(s, b, l, f, o, n)
640#define SETSOCKOPT(s, l, o, v, n) _win_setsockopt(s, l, o, v, n)
641#define SHUTDOWN(s, h) _win_shutdown(s, h)
642#define SOCKET(a, t, p) _win_socket(a, t, p)
643#define GETHOSTBYADDR(a, l, t) _win_gethostbyname(a, l, t)
644#define GETHOSTBYNAME(n) _win_gethostbyname(n)
645#define GETTIMEOFDAY(t, n) _win_gettimeofday(t, n)
646#define INSQUE(e, p) _win_insque(e, p)
647#define REMQUE(e) _win_remque(e)
648#define HSEARCH(i, a) _win_hsearch(i, a)
649#define HCREATE(n) _win_hcreate(n)
650#define HDESTROY() _win_hdestroy()
651#define HSEARCH_R(i, a, r, h) _win_hsearch_r(i, a, r, h)
652#define HCREATE_R(n, h) _win_hcreate_r(n, h)
653#define HDESTROY_R(h) _win_hdestroy_r(h)
654#define TSEARCH(k, r, c) _win_tsearch(k, r, c)
655#define TFIND(k, r, c) _win_tfind(k, r, c)
656#define TDELETE(k, r, c) _win_tdelete(k, r, c)
657#define TWALK(r, a) _win_twalk(r, a)
658#define TDESTROY(r, f) _win_tdestroy(r, f)
659#define LFIND(k, b, n, s, c) _win_lfind(k, b, n, s, c)
660#define LSEARCH(k, b, n, s, c) _win_lsearch(k, b, n, s, c)
661#endif
662
663/* search.h */
664
665/* Prototype structure for a linked-list data structure.
666 This is the type used by the `insque' and `remque' functions. */
667
668 struct PLIBC_SEARCH_QELEM
669 {
670 struct qelem *q_forw;
671 struct qelem *q_back;
672 char q_data[1];
673 };
674
675
676/* Insert ELEM into a doubly-linked list, after PREV. */
677 void _win_insque (void *__elem, void *__prev);
678
679/* Unlink ELEM from the doubly-linked list that it is in. */
680 void _win_remque (void *__elem);
681
682
683/* For use with hsearch(3). */
684 typedef int (*PLIBC_SEARCH__compar_fn_t) (__const void *, __const void *);
685
686 typedef PLIBC_SEARCH__compar_fn_t _win_comparison_fn_t;
687
688/* Action which shall be performed in the call the hsearch. */
689 typedef enum
690 {
691 PLIBC_SEARCH_FIND,
692 PLIBC_SEARCH_ENTER
693 }
694 PLIBC_SEARCH_ACTION;
695
696 typedef struct PLIBC_SEARCH_entry
697 {
698 char *key;
699 void *data;
700 }
701 PLIBC_SEARCH_ENTRY;
702
703/* The reentrant version has no static variables to maintain the state.
704 Instead the interface of all functions is extended to take an argument
705 which describes the current status. */
706 typedef struct _PLIBC_SEARCH_ENTRY
707 {
708 unsigned int used;
709 PLIBC_SEARCH_ENTRY entry;
710 }
711 _PLIBC_SEARCH_ENTRY;
712
713
714/* Family of hash table handling functions. The functions also
715 have reentrant counterparts ending with _r. The non-reentrant
716 functions all work on a signle internal hashing table. */
717
718/* Search for entry matching ITEM.key in internal hash table. If
719 ACTION is `FIND' return found entry or signal error by returning
720 NULL. If ACTION is `ENTER' replace existing data (if any) with
721 ITEM.data. */
722 PLIBC_SEARCH_ENTRY *_win_hsearch (PLIBC_SEARCH_ENTRY __item,
723 PLIBC_SEARCH_ACTION __action);
724
725/* Create a new hashing table which will at most contain NEL elements. */
726 int _win_hcreate (size_t __nel);
727
728/* Destroy current internal hashing table. */
729 void _win_hdestroy (void);
730
731/* Data type for reentrant functions. */
732 struct PLIBC_SEARCH_hsearch_data
733 {
734 struct _PLIBC_SEARCH_ENTRY *table;
735 unsigned int size;
736 unsigned int filled;
737 };
738
739/* Reentrant versions which can handle multiple hashing tables at the
740 same time. */
741 int _win_hsearch_r (PLIBC_SEARCH_ENTRY __item, PLIBC_SEARCH_ACTION __action,
742 PLIBC_SEARCH_ENTRY ** __retval,
743 struct PLIBC_SEARCH_hsearch_data *__htab);
744 int _win_hcreate_r (size_t __nel, struct PLIBC_SEARCH_hsearch_data *__htab);
745 void _win_hdestroy_r (struct PLIBC_SEARCH_hsearch_data *__htab);
746
747
748/* The tsearch routines are very interesting. They make many
749 assumptions about the compiler. It assumes that the first field
750 in node must be the "key" field, which points to the datum.
751 Everything depends on that. */
752/* For tsearch */
753 typedef enum
754 {
755 PLIBC_SEARCH_preorder,
756 PLIBC_SEARCH_postorder,
757 PLIBC_SEARCH_endorder,
758 PLIBC_SEARCH_leaf
759 }
760 PLIBC_SEARCH_VISIT;
761
762/* Search for an entry matching the given KEY in the tree pointed to
763 by *ROOTP and insert a new element if not found. */
764 void *_win_tsearch (__const void *__key, void **__rootp,
765 PLIBC_SEARCH__compar_fn_t __compar);
766
767/* Search for an entry matching the given KEY in the tree pointed to
768 by *ROOTP. If no matching entry is available return NULL. */
769 void *_win_tfind (__const void *__key, void *__const * __rootp,
770 PLIBC_SEARCH__compar_fn_t __compar);
771
772/* Remove the element matching KEY from the tree pointed to by *ROOTP. */
773 void *_win_tdelete (__const void *__restrict __key, void **__restrict __rootp,
774 PLIBC_SEARCH__compar_fn_t __compar);
775
776 typedef void (*PLIBC_SEARCH__action_fn_t) (__const void *__nodep,
777 PLIBC_SEARCH_VISIT __value,
778 int __level);
779
780/* Walk through the whole tree and call the ACTION callback for every node
781 or leaf. */
782 void _win_twalk (__const void *__root, PLIBC_SEARCH__action_fn_t __action);
783
784/* Callback type for function to free a tree node. If the keys are atomic
785 data this function should do nothing. */
786 typedef void (*PLIBC_SEARCH__free_fn_t) (void *__nodep);
787
788/* Destroy the whole tree, call FREEFCT for each node or leaf. */
789 void _win_tdestroy (void *__root, PLIBC_SEARCH__free_fn_t __freefct);
790
791
792/* Perform linear search for KEY by comparing by COMPAR in an array
793 [BASE,BASE+NMEMB*SIZE). */
794 void *_win_lfind (__const void *__key, __const void *__base, size_t * __nmemb,
795 size_t __size, PLIBC_SEARCH__compar_fn_t __compar);
796
797/* Perform linear search for KEY by comparing by COMPAR function in
798 array [BASE,BASE+NMEMB*SIZE) and insert entry if not found. */
799 void *_win_lsearch (__const void *__key, void *__base, size_t * __nmemb,
800 size_t __size, PLIBC_SEARCH__compar_fn_t __compar);
801
802
803#ifdef __cplusplus
804}
805#endif
806
807
808#endif //_PLIBC_H_
809
810/* end of plibc.h */
diff --git a/pathologist/src/mi/Makefile.am b/pathologist/src/mi/Makefile.am
new file mode 100644
index 0000000..1248080
--- /dev/null
+++ b/pathologist/src/mi/Makefile.am
@@ -0,0 +1,29 @@
1INCLUDES = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage -O0
9 XLIB = -lgcov
10endif
11
12lib_LTLIBRARIES = libmi.la
13
14libmi_la_SOURCES = \
15 gdbmi_alloc.c \
16 gdbmi_breakpoint.c \
17 gdbmi_connect.c \
18 gdbmi_data_man.c \
19 gdbmi_error.c \
20 gdbmi_get_free_pty.c \
21 gdbmi_get_free_vt.c \
22 gdbmi_misc.c \
23 gdbmi_parse.c \
24 gdbmi_prg_control.c \
25 gdbmi_stack_man.c \
26 gdbmi_symbol_query.c \
27 gdbmi_target_man.c \
28 gdbmi_thread.c \
29 gdbmi_var_obj.c \ No newline at end of file
diff --git a/pathologist/src/mi/gdbmi_alloc.c b/pathologist/src/mi/gdbmi_alloc.c
new file mode 100644
index 0000000..0fe6e14
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_alloc.c
@@ -0,0 +1,308 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Allocator.
7 Comments:
8 Most alloc/free routines are here. Free routines must accept NULL
9pointers. Alloc functions must set mi_error. @<p>
10
11***************************************************************************/
12
13#include "gdbmi.h"
14
15void *mi_calloc(size_t count, size_t sz)
16{
17 void *res=calloc(count,sz);
18 if (!res)
19 mi_error=MI_OUT_OF_MEMORY;
20 return res;
21}
22
23void *mi_calloc1(size_t sz)
24{
25 return mi_calloc(1,sz);
26}
27
28char *mi_malloc(size_t sz)
29{
30 char *res=malloc(sz);
31 if (!res)
32 mi_error=MI_OUT_OF_MEMORY;
33 return res;
34}
35
36mi_results *mi_alloc_results(void)
37{
38 return (mi_results *)mi_calloc1(sizeof(mi_results));
39}
40
41mi_output *mi_alloc_output(void)
42{
43 return (mi_output *)mi_calloc1(sizeof(mi_output));
44}
45
46mi_frames *mi_alloc_frames(void)
47{
48 return (mi_frames *)mi_calloc1(sizeof(mi_frames));
49}
50
51mi_gvar *mi_alloc_gvar(void)
52{
53 return (mi_gvar *)mi_calloc1(sizeof(mi_gvar));
54}
55
56mi_gvar_chg *mi_alloc_gvar_chg(void)
57{
58 return (mi_gvar_chg *)mi_calloc1(sizeof(mi_gvar_chg));
59}
60
61mi_bkpt *mi_alloc_bkpt(void)
62{
63 mi_bkpt *b=(mi_bkpt *)mi_calloc1(sizeof(mi_bkpt));
64 if (b)
65 {
66 b->thread=-1;
67 b->ignore=-1;
68 }
69 return b;
70}
71
72mi_wp *mi_alloc_wp(void)
73{
74 return (mi_wp *)mi_calloc1(sizeof(mi_wp));
75}
76
77mi_stop *mi_alloc_stop(void)
78{
79 return (mi_stop *)mi_calloc1(sizeof(mi_stop));
80}
81
82mi_asm_insns *mi_alloc_asm_insns(void)
83{
84 return (mi_asm_insns *)mi_calloc1(sizeof(mi_asm_insns));
85}
86
87mi_asm_insn *mi_alloc_asm_insn(void)
88{
89 return (mi_asm_insn *)mi_calloc1(sizeof(mi_asm_insn));
90}
91
92mi_chg_reg *mi_alloc_chg_reg(void)
93{
94 return (mi_chg_reg *)mi_calloc1(sizeof(mi_chg_reg));
95}
96
97/*****************************************************************************
98 Free functions
99*****************************************************************************/
100
101void mi_free_frames(mi_frames *f)
102{
103 mi_frames *aux;
104
105 while (f)
106 {
107 free(f->func);
108 free(f->file);
109 free(f->from);
110 mi_free_results(f->args);
111 aux=f->next;
112 free(f);
113 f=aux;
114 }
115}
116
117void mi_free_bkpt(mi_bkpt *b)
118{
119 mi_bkpt *aux;
120
121 while (b)
122 {
123 free(b->func);
124 free(b->file);
125 free(b->file_abs);
126 free(b->cond);
127 aux=b->next;
128 free(b);
129 b=aux;
130 }
131}
132
133void mi_free_gvar(mi_gvar *v)
134{
135 mi_gvar *aux;
136
137 while (v)
138 {
139 free(v->name);
140 free(v->type);
141 free(v->exp);
142 free(v->value);
143 if (v->numchild && v->child)
144 mi_free_gvar(v->child);
145 aux=v->next;
146 free(v);
147 v=aux;
148 }
149}
150
151void mi_free_gvar_chg(mi_gvar_chg *p)
152{
153 mi_gvar_chg *aux;
154
155 while (p)
156 {
157 free(p->name);
158 free(p->new_type);
159 aux=p->next;
160 free(p);
161 p=aux;
162 }
163}
164
165void mi_free_results_but(mi_results *r, mi_results *no)
166{
167 mi_results *aux;
168
169 while (r)
170 {
171 if (r==no)
172 {
173 aux=r->next;
174 r->next=NULL;
175 r=aux;
176 }
177 else
178 {
179 free(r->var);
180 switch (r->type)
181 {
182 case t_const:
183 free(r->v.cstr);
184 break;
185 case t_tuple:
186 case t_list:
187 mi_free_results_but(r->v.rs,no);
188 break;
189 }
190 aux=r->next;
191 free(r);
192 r=aux;
193 }
194 }
195}
196
197void mi_free_results(mi_results *r)
198{
199 mi_free_results_but(r,NULL);
200}
201
202void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r)
203{
204 mi_output *aux;
205
206 while (r)
207 {
208 if (r==no)
209 {
210 aux=r->next;
211 r->next=NULL;
212 r=aux;
213 }
214 else
215 {
216 if (r->c)
217 mi_free_results_but(r->c,no_r);
218 aux=r->next;
219 free(r);
220 r=aux;
221 }
222 }
223}
224
225void mi_free_output(mi_output *r)
226{
227 mi_free_output_but(r,NULL,NULL);
228}
229
230void mi_free_stop(mi_stop *s)
231{
232 if (!s)
233 return;
234 mi_free_frames(s->frame);
235 mi_free_wp(s->wp);
236 free(s->wp_old);
237 free(s->wp_val);
238 free(s->gdb_result_var);
239 free(s->return_value);
240 free(s->signal_name);
241 free(s->signal_meaning);
242 free(s);
243}
244
245void mi_free_wp(mi_wp *wp)
246{
247 mi_wp *aux;
248 while (wp)
249 {
250 free(wp->exp);
251 aux=wp->next;
252 free(wp);
253 wp=aux;
254 }
255}
256
257void mi_free_asm_insns(mi_asm_insns *i)
258{
259 mi_asm_insns *aux;
260
261 while (i)
262 {
263 free(i->file);
264 mi_free_asm_insn(i->ins);
265 aux=i->next;
266 free(i);
267 i=aux;
268 }
269}
270
271void mi_free_asm_insn(mi_asm_insn *i)
272{
273 mi_asm_insn *aux;
274
275 while (i)
276 {
277 free(i->func);
278 free(i->inst);
279 aux=i->next;
280 free(i);
281 i=aux;
282 }
283}
284
285/*void mi_free_charp_list(char **l)
286{
287 char **c=l;
288 while (c)
289 {
290 free(*c);
291 c++;
292 }
293 free(l);
294}*/
295
296void mi_free_chg_reg(mi_chg_reg *r)
297{
298 mi_chg_reg *aux;
299 while (r)
300 {
301 free(r->val);
302 free(r->name);
303 aux=r->next;
304 free(r);
305 r=aux;
306 }
307}
308
diff --git a/pathologist/src/mi/gdbmi_breakpoint.c b/pathologist/src/mi/gdbmi_breakpoint.c
new file mode 100644
index 0000000..f91cc3e
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_breakpoint.c
@@ -0,0 +1,265 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Breakpoint table commands.
7 Comments:
8 GDB/MI commands for the "Breakpoint Table Commands" section.
9 @<p>
10@<pre>
11gdb command: Implemented?
12
13-break-after Yes
14-break-condition Yes
15-break-delete Yes
16-break-disable Yes
17-break-enable Yes
18-break-info N.A. (info break NUMBER) (*)
19-break-insert Yes
20-break-list No (*)
21-break-watch Yes
22@</pre>
23
24(*) I think the program should keep track of the breakpoints, so it will
25be implemented when I have more time. @<p>
26
27***************************************************************************/
28
29#include "gdbmi.h"
30
31/* Low level versions. */
32
33void mi_break_insert_fl(mi_h *h, const char *file, int line)
34{
35 mi_send(h,"-break-insert %s:%d\n",file,line);
36}
37
38void mi_break_insert(mi_h *h, int temporary, int hard_assist,
39 const char *cond, int count, int thread,
40 const char *where)
41{
42 char s_count[32];
43 char s_thread[32];
44
45 if (count>=0)
46 snprintf(s_count,32,"%d",count);
47 if (thread>=0)
48 snprintf(s_thread,32,"%d",thread);
49 if (cond)
50 // Conditions may contain spaces, in fact, if they don't gdb will add
51 // them after parsing. Enclosing the expression with "" solves the
52 // problem.
53 mi_send(h,"-break-insert %s %s -c \"%s\" %s %s %s %s %s\n",
54 temporary ? "-t" : "",
55 hard_assist ? "-h" : "",
56 cond,
57 count>=0 ? "-i" : "", count>=0 ? s_count : "",
58 thread>=0 ? "-p" : "", thread>=0 ? s_thread : "",
59 where);
60 else
61 mi_send(h,"-break-insert %s %s %s %s %s %s %s\n",
62 temporary ? "-t" : "",
63 hard_assist ? "-h" : "",
64 count>=0 ? "-i" : "", count>=0 ? s_count : "",
65 thread>=0 ? "-p" : "", thread>=0 ? s_thread : "",
66 where);
67}
68
69void mi_break_insert_flf(mi_h *h, const char *file, int line, int temporary,
70 int hard_assist, const char *cond, int count,
71 int thread)
72{
73 char s_count[32];
74 char s_thread[32];
75
76 if (count>=0)
77 snprintf(s_count,32,"%d",count);
78 if (thread>=0)
79 snprintf(s_thread,32,"%d",thread);
80 mi_send(h,"-break-insert %s %s %s %s %s %s %s %s %s:%d\n",
81 temporary ? "-t" : "",
82 hard_assist ? "-h" : "",
83 cond ? "-c" : "", cond ? cond : "",
84 count>=0 ? "-i" : "", count>=0 ? s_count : "",
85 thread>=0 ? "-p" : "", thread>=0 ? s_thread : "",
86 file,line);
87}
88
89void mi_break_delete(mi_h *h, int number)
90{
91 mi_send(h,"-break-delete %d\n",number);
92}
93
94void mi_break_after(mi_h *h, int number, int count)
95{
96 mi_send(h,"-break-after %d %d\n",number,count);
97}
98
99void mi_break_condition(mi_h *h, int number, const char *condition)
100{
101 mi_send(h,"-break-condition %d %s\n",number,condition);
102}
103
104void mi_break_enable(mi_h *h, int number)
105{
106 mi_send(h,"-break-enable %d\n",number);
107}
108
109void mi_break_disable(mi_h *h, int number)
110{
111 mi_send(h,"-break-disable %d\n",number);
112}
113
114void mi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp)
115{
116 if (mode==wm_write)
117 mi_send(h,"-break-watch \"%s\"\n",exp);
118 else
119 mi_send(h,"-break-watch -%c \"%s\"\n",mode==wm_rw ? 'a' : 'r',exp);
120}
121
122/* High level versions. */
123
124/**[txh]********************************************************************
125
126 Description:
127 Insert a breakpoint at file:line.
128
129 Command: -break-insert file:line
130 Return: A new mi_bkpt structure with info about the breakpoint. NULL on
131error.
132
133***************************************************************************/
134
135mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line)
136{
137 mi_break_insert_fl(h,file,line);
138 return mi_res_bkpt(h);
139}
140
141/**[txh]********************************************************************
142
143 Description:
144 Insert a breakpoint, all available options.
145
146 Command: -break-insert
147 Return: A new mi_bkpt structure with info about the breakpoint. NULL on
148error.
149
150***************************************************************************/
151
152mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
153 const char *cond, int count, int thread,
154 const char *where)
155{
156 mi_break_insert(h,temporary,hard_assist,cond,count,thread,where);
157 return mi_res_bkpt(h);
158}
159
160/**[txh]********************************************************************
161
162 Description:
163 Insert a breakpoint, all available options.
164
165 Command: -break-insert [ops] file:line
166 Return: A new mi_bkpt structure with info about the breakpoint. NULL on
167error.
168
169***************************************************************************/
170
171mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
172 int temporary, int hard_assist,
173 const char *cond, int count, int thread)
174{
175 mi_break_insert_flf(h,file,line,temporary,hard_assist,cond,count,thread);
176 return mi_res_bkpt(h);
177}
178
179/**[txh]********************************************************************
180
181 Description:
182 Remove a breakpoint.
183
184 Command: -break-delete
185 Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
186console.
187
188***************************************************************************/
189
190int gmi_break_delete(mi_h *h, int number)
191{
192 mi_break_delete(h,number);
193 return mi_res_simple_done(h);
194}
195
196/**[txh]********************************************************************
197
198 Description:
199 Modify the "ignore" count for a breakpoint.
200
201 Command: -break-after
202 Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
203console.
204
205***************************************************************************/
206
207int gmi_break_set_times(mi_h *h, int number, int count)
208{
209 mi_break_after(h,number,count);
210 return mi_res_simple_done(h);
211}
212
213/**[txh]********************************************************************
214
215 Description:
216 Associate a condition with the breakpoint.
217
218 Command: -break-condition
219 Return: !=0 OK
220
221***************************************************************************/
222
223int gmi_break_set_condition(mi_h *h, int number, const char *condition)
224{
225 mi_break_condition(h,number,condition);
226 return mi_res_simple_done(h);
227}
228
229/**[txh]********************************************************************
230
231 Description:
232 Enable or disable a breakpoint.
233
234 Command: -break-enable + -break-disable
235 Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
236console.
237
238***************************************************************************/
239
240int gmi_break_state(mi_h *h, int number, int enable)
241{
242 if (enable)
243 mi_break_enable(h,number);
244 else
245 mi_break_disable(h,number);
246 return mi_res_simple_done(h);
247}
248
249/**[txh]********************************************************************
250
251 Description:
252 Set a watchpoint. It doesn't work for remote targets!
253
254 Command: -break-watch
255 Return: A new mi_wp structure with info about the watchpoint. NULL on
256error.
257
258***************************************************************************/
259
260mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp)
261{
262 mi_break_watch(h,mode,exp);
263 return mi_res_wp(h);
264}
265
diff --git a/pathologist/src/mi/gdbmi_connect.c b/pathologist/src/mi/gdbmi_connect.c
new file mode 100644
index 0000000..b9f3754
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_connect.c
@@ -0,0 +1,885 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2009 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Connect.
7 Comments:
8 This module handles the dialog with gdb, including starting and stopping
9gdb.
10 @<p>
11
12GDB Bug workaround for "file -readnow": I tried to workaround a bug using
13it but looks like this option also have bugs!!!! so I have to use the
14command line option --readnow.
15It also have a bug!!!! when the binary is changed and gdb must reload it
16this option is ignored. So it looks like we have no solution but 3 gdb bugs
17in a row.
18
19***************************************************************************/
20
21#include <sys/types.h>
22#include <unistd.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <sys/wait.h>
26#include <fcntl.h>
27#include <string.h>
28#include <stdarg.h>
29#include <limits.h>
30#include <errno.h>
31#include <signal.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include "plibc.h"
35
36#include "gdbmi.h"
37#ifndef _GNU_SOURCE
38#define _GNU_SOURCE
39#endif
40
41#ifndef TEMP_FAILURE_RETRY
42 #define TEMP_FAILURE_RETRY(a) (a)
43#endif
44
45int mi_error=MI_OK;
46char *mi_error_from_gdb=NULL;
47static char *gdb_exe=NULL;
48static char *xterm_exe=NULL;
49static char *gdb_start=NULL;
50static char *gdb_conn=NULL;
51static char *main_func=NULL;
52static char disable_psym_search_workaround=0;
53
54mi_h *mi_alloc_h()
55{
56 mi_h *h=(mi_h *)calloc(1,sizeof(mi_h));
57 if (!h)
58 {
59 mi_error=MI_OUT_OF_MEMORY;
60 return NULL;
61 }
62 h->to_gdb[0]=h->to_gdb[1]=h->from_gdb[0]=h->from_gdb[1]=-1;
63 h->pid=-1;
64 return h;
65}
66
67int mi_check_running_pid(pid_t pid)
68{
69 int status;
70
71 if (pid<=0)
72 return 0;
73 /* If waitpid returns the number of our child means it communicated
74 to as a termination status. */
75 if (waitpid(pid,&status,WNOHANG)==pid)
76 {
77 pid=0;
78 return 0;
79 }
80 return 1;
81}
82
83int mi_check_running(mi_h *h)
84{
85 return !h->died && mi_check_running_pid(h->pid);
86}
87
88void mi_kill_child(pid_t pid)
89{
90 kill(pid,SIGTERM);
91 usleep(100000);
92 if (mi_check_running_pid(pid))
93 {
94 int status;
95 kill(pid,SIGKILL);
96 waitpid(pid,&status,0);
97 }
98}
99
100void mi_free_h(mi_h **handle)
101{
102 mi_h *h=*handle;
103 if (h->to_gdb[0]>=0)
104 close(h->to_gdb[0]);
105 if (h->to)
106 fclose(h->to);
107 else if (h->to_gdb[1]>=0)
108 close(h->to_gdb[1]);
109 if (h->from)
110 fclose(h->from);
111 else if (h->from_gdb[0]>=0)
112 close(h->from_gdb[0]);
113 if (h->from_gdb[1]>=0)
114 close(h->from_gdb[1]);
115 if (mi_check_running(h))
116 {/* GDB is running! */
117 mi_kill_child(h->pid);
118 }
119 if (h->line)
120 free(h->line);
121 mi_free_output(h->po);
122 free(h->catched_console);
123 free(h);
124 *handle=NULL;
125}
126
127void mi_set_nonblk(int h)
128{
129 int flf;
130 flf=fcntl(h,F_GETFL,0);
131 flf=flf | O_NONBLOCK;
132 fcntl(h,F_SETFL,flf);
133}
134
135int mi_getline(mi_h *h)
136{
137 char c;
138
139 while (read(h->from_gdb[0],&c,1)==1)
140 {
141 if (h->lread>=h->llen)
142 {
143 h->llen=h->lread+128;
144 h->line=(char *)realloc(h->line,h->llen);
145 if (!h->line)
146 {
147 h->llen=0;
148 h->lread=0;
149 return -1;
150 }
151 }
152 if (c=='\n')
153 {
154 int ret=h->lread;
155 h->line[ret]=0;
156 h->lread=0;
157 return ret;
158 }
159 h->line[h->lread]=c;
160 h->lread++;
161 }
162 return 0;
163}
164
165char *get_cstr(mi_output *o)
166{
167 if (!o->c || o->c->type!=t_const)
168 return NULL;
169 return o->c->v.cstr;
170}
171
172int mi_get_response(mi_h *h)
173{
174 int l=mi_getline(h);
175 if (!l)
176 return 0;
177
178 if (h->from_gdb_echo)
179 h->from_gdb_echo(h->line,h->from_gdb_echo_data);
180 if (strncmp(h->line,"(gdb)",5)==0)
181 {/* End of response. */
182 return 1;
183 }
184 else
185 {/* Add to the response. */
186 mi_output *o;
187 int add=1, is_exit=0;
188 o=mi_parse_gdb_output(h->line);
189
190 if (!o)
191 return 0;
192 /* Tunneled streams callbacks. */
193 if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_STREAM)
194 {
195 char *aux;
196 add=0;
197 switch (o->sstype)
198 {
199 case MI_SST_CONSOLE:
200 aux=get_cstr(o);
201 if (h->console)
202 h->console(aux,h->console_data);
203 if (h->catch_console && aux)
204 {
205 h->catch_console--;
206 if (!h->catch_console)
207 {
208 free(h->catched_console);
209 h->catched_console=strdup(aux);
210 }
211 }
212 break;
213 case MI_SST_TARGET:
214 /* This one seems to be useless. */
215 if (h->target)
216 h->target(get_cstr(o),h->target_data);
217 break;
218 case MI_SST_LOG:
219 if (h->log)
220 h->log(get_cstr(o),h->log_data);
221 break;
222 }
223 }
224 else if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_ASYNC)
225 {
226 if (h->async)
227 h->async(o,h->async_data);
228 }
229 else if (o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_ERROR)
230 {/* Error from gdb, record it. */
231 mi_error=MI_FROM_GDB;
232 free(mi_error_from_gdb);
233 mi_error_from_gdb=NULL;
234 if (o->c && strcmp(o->c->var,"msg")==0 && o->c->type==t_const)
235 mi_error_from_gdb=strdup(o->c->v.cstr);
236 }
237 is_exit=(o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_EXIT);
238 /* Add to the list of responses. */
239 if (add)
240 {
241 if (h->last)
242 h->last->next=o;
243 else
244 h->po=o;
245 h->last=o;
246 }
247 else
248 mi_free_output(o);
249 /* Exit RR means gdb exited, we won't get a new prompt ;-) */
250 if (is_exit)
251 return 1;
252 }
253
254 return 0;
255}
256
257mi_output *mi_retire_response(mi_h *h)
258{
259 mi_output *ret=h->po;
260 h->po=h->last=NULL;
261 return ret;
262}
263
264mi_output *mi_get_response_blk(mi_h *h)
265{
266 int r;
267 /* Sometimes gdb dies. */
268 if (!mi_check_running(h))
269 {
270 h->died=1;
271 mi_error=MI_GDB_DIED;
272 return NULL;
273 }
274 do
275 {
276 /*
277 That's a must. If we just keep trying to read and failing things
278 become really sloooowwww. Instead we try and if it fails we wait
279 until something is available.
280 TODO: Implement something with the time out, a callback to ask the
281 application is we have to wait or not could be a good thing.
282 */
283 fd_set set;
284 struct timeval timeout;
285 int ret;
286
287 r=mi_get_response(h);
288 if (r)
289 return mi_retire_response(h);
290
291 FD_ZERO(&set);
292 FD_SET(h->from_gdb[0],&set);
293 timeout.tv_sec=h->time_out;
294 timeout.tv_usec=0;
295 ret=TEMP_FAILURE_RETRY(select(FD_SETSIZE,&set,NULL,NULL,&timeout));
296 if (!ret)
297 {
298 if (!mi_check_running(h))
299 {
300 h->died=1;
301 mi_error=MI_GDB_DIED;
302 return NULL;
303 }
304 if (h->time_out_cb)
305 ret=h->time_out_cb(h->time_out_cb_data);
306 if (!ret)
307 {
308 mi_error=MI_GDB_TIME_OUT;
309 return NULL;
310 }
311 }
312 }
313 while (!r);
314
315 return NULL;
316}
317
318void mi_send_commands(mi_h *h, const char *file)
319{
320 FILE *f;
321 char b[PATH_MAX];
322
323 //printf("File: %s\n",file);
324 if (!file)
325 return;
326 f=fopen(file,"rt");
327 if (!f)
328 return;
329 while (!feof(f))
330 {
331 if (fgets(b,PATH_MAX,f))
332 {
333 //printf("Send: %s\n",b);
334 mi_send (h, "%s", b);
335 mi_res_simple_done(h);
336 }
337 }
338 fclose(f);
339}
340
341void mi_send_target_commands(mi_h *h)
342{
343 mi_send_commands(h,gdb_conn);
344}
345
346/**[txh]********************************************************************
347
348 Description:
349 Connect to a local copy of gdb. Note that the mi_h structure is something
350similar to a "FILE *" for stdio.
351
352 Return: A new mi_h structure or NULL on error.
353
354***************************************************************************/
355
356mi_h *mi_connect_local()
357{
358 mi_h *h;
359 const char *gdb=mi_get_gdb_exe();
360
361 /* Start without error. */
362 mi_error=MI_OK;
363 /* Verify we have a GDB binary. */
364 if (access(gdb,X_OK))
365 {
366 mi_error=MI_MISSING_GDB;
367 return NULL;
368 }
369 /* Alloc the handle structure. */
370 h=mi_alloc_h();
371 if (!h)
372 return h;
373 h->time_out=MI_DEFAULT_TIME_OUT;
374 /* Create the pipes to connect with the child. */
375 if (pipe(h->to_gdb) || pipe(h->from_gdb))
376 {
377 mi_error=MI_PIPE_CREATE;
378 mi_free_h(&h);
379 return NULL;
380 }
381 mi_set_nonblk(h->to_gdb[1]);
382 mi_set_nonblk(h->from_gdb[0]);
383 /* Associate streams to the file handles. */
384 h->to=fdopen(h->to_gdb[1],"w");
385 h->from=fdopen(h->from_gdb[0],"r");
386 if (!h->to || !h->from)
387 {
388 mi_error=MI_PIPE_CREATE;
389 mi_free_h(&h);
390 return NULL;
391 }
392 /* Create the child. */
393 h->pid=fork();
394 if (h->pid==0)
395 {/* We are the child. */
396 char *argv[5];
397 /* Connect stdin/out to the pipes. */
398 dup2(h->to_gdb[0],STDIN_FILENO);
399 dup2(h->from_gdb[1],STDOUT_FILENO);
400 /* Pass the control to gdb. */
401 argv[0]=(char *)gdb; /* Is that OK? */
402 argv[1]="--interpreter=mi";
403 argv[2]="--quiet";
404 argv[3]=disable_psym_search_workaround ? 0 : "--readnow";
405 argv[4]=0;
406 execvp(argv[0],argv);
407 /* We get here only if exec failed. */
408 _exit(127);
409 }
410 /* We are the parent. */
411 if (h->pid==-1)
412 {/* Fork failed. */
413 mi_error=MI_FORK;
414 mi_free_h(&h);
415 return NULL;
416 }
417 if (!mi_check_running(h))
418 {
419 mi_error=MI_DEBUGGER_RUN;
420 mi_free_h(&h);
421 return NULL;
422 }
423 /* Wait for the prompt. */
424 mi_get_response_blk(h);
425 /* Send the start-up commands */
426 mi_send_commands(h,gdb_start);
427
428 return h;
429}
430
431/**[txh]********************************************************************
432
433 Description:
434 Close connection. You should ask gdb to quit first gmi_gdb_exit.
435
436***************************************************************************/
437
438void mi_disconnect(mi_h *h)
439{
440 mi_free_h(&h);
441 free(mi_error_from_gdb);
442 mi_error_from_gdb=NULL;
443}
444
445void mi_set_console_cb(mi_h *h, stream_cb cb, void *data)
446{
447 h->console=cb;
448 h->console_data=data;
449}
450
451void mi_set_target_cb(mi_h *h, stream_cb cb, void *data)
452{
453 h->target=cb;
454 h->target_data=data;
455}
456
457void mi_set_log_cb(mi_h *h, stream_cb cb, void *data)
458{
459 h->log=cb;
460 h->log_data=data;
461}
462
463stream_cb mi_get_console_cb(mi_h *h, void **data)
464{
465 if (data)
466 *data=h->console_data;
467 return h->console;
468}
469
470stream_cb mi_get_target_cb(mi_h *h, void **data)
471{
472 if (data)
473 *data=h->target_data;
474 return h->target;
475}
476
477stream_cb mi_get_log_cb(mi_h *h, void **data)
478{
479 if (data)
480 *data=h->log_data;
481 return h->log;
482}
483
484void mi_set_async_cb(mi_h *h, async_cb cb, void *data)
485{
486 h->async=cb;
487 h->async_data=data;
488}
489
490async_cb mi_get_async_cb(mi_h *h, void **data)
491{
492 if (data)
493 *data=h->async_data;
494 return h->async;
495}
496
497void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data)
498{
499 h->to_gdb_echo=cb;
500 h->to_gdb_echo_data=data;
501}
502
503void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data)
504{
505 h->from_gdb_echo=cb;
506 h->from_gdb_echo_data=data;
507}
508
509stream_cb mi_get_to_gdb_cb(mi_h *h, void **data)
510{
511 if (data)
512 *data=h->to_gdb_echo_data;
513 return h->to_gdb_echo;
514}
515
516stream_cb mi_get_from_gdb_cb(mi_h *h, void **data)
517{
518 if (data)
519 *data=h->from_gdb_echo_data;
520 return h->from_gdb_echo;
521}
522
523void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data)
524{
525 h->time_out_cb=cb;
526 h->time_out_cb_data=data;
527}
528
529tm_cb mi_get_time_out_cb(mi_h *h, void **data)
530{
531 if (data)
532 *data=h->time_out_cb_data;
533 return h->time_out_cb;
534}
535
536void mi_set_time_out(mi_h *h, int to)
537{
538 h->time_out=to;
539}
540
541int mi_get_time_out(mi_h *h)
542{
543 return h->time_out;
544}
545
546int mi_send(mi_h *h, const char *format, ...)
547{
548 int ret;
549 char *str;
550 va_list argptr;
551
552 if (h->died)
553 return 0;
554
555 va_start(argptr,format);
556 ret=vasprintf(&str,format,argptr);
557 va_end(argptr);
558 if (-1 != ret)
559 {
560 fputs(str,h->to);
561 fflush(h->to);
562 if (h->to_gdb_echo)
563 h->to_gdb_echo(str,h->to_gdb_echo_data);
564 free(str);
565 }
566 else
567 {
568 abort ();
569 }
570
571 return ret;
572}
573
574void mi_clean_up_globals()
575{
576 free(gdb_exe);
577 gdb_exe=NULL;
578 free(xterm_exe);
579 xterm_exe=NULL;
580 free(gdb_start);
581 gdb_start=NULL;
582 free(gdb_conn);
583 gdb_conn=NULL;
584 free(main_func);
585 main_func=NULL;
586}
587
588void mi_register_exit()
589{
590 static int registered=0;
591 if (!registered)
592 {
593 registered=1;
594 atexit(mi_clean_up_globals);
595 }
596}
597
598void mi_set_gdb_exe(const char *name)
599{
600 free(gdb_exe);
601 gdb_exe=name ? strdup(name) : NULL;
602 mi_register_exit();
603}
604
605void mi_set_gdb_start(const char *name)
606{
607 free(gdb_start);
608 gdb_start=name ? strdup(name) : NULL;
609 mi_register_exit();
610}
611
612void mi_set_gdb_conn(const char *name)
613{
614 free(gdb_conn);
615 gdb_conn=name ? strdup(name) : NULL;
616 mi_register_exit();
617}
618
619static
620char *mi_search_in_path(const char *file)
621{
622 char *path, *pt, *r;
623 char test[PATH_MAX];
624 struct stat st;
625
626 path=getenv("PATH");
627 if (!path)
628 return NULL;
629 pt=strdup(path);
630 r=strtok(pt,PATH_SEPARATOR_STR);
631 while (r)
632 {
633 strcpy(test,r);
634 strcat(test,"/");
635 strcat(test,file);
636 if (stat(test,&st)==0 && S_ISREG(st.st_mode))
637 {
638 free(pt);
639 return strdup(test);
640 }
641 r=strtok(NULL,PATH_SEPARATOR_STR);
642 }
643 free(pt);
644 return NULL;
645}
646
647const char *mi_get_gdb_exe()
648{
649 if (!gdb_exe)
650 {/* Look for gdb in path */
651 gdb_exe=mi_search_in_path("gdb");
652 if (!gdb_exe)
653 return "/usr/bin/gdb";
654 }
655 return gdb_exe;
656}
657
658const char *mi_get_gdb_start()
659{
660 return gdb_start;
661}
662
663const char *mi_get_gdb_conn()
664{
665 return gdb_conn;
666}
667
668void mi_set_xterm_exe(const char *name)
669{
670 free(xterm_exe);
671 xterm_exe=name ? strdup(name) : NULL;
672 mi_register_exit();
673}
674
675const char *mi_get_xterm_exe()
676{
677 if (!xterm_exe)
678 {/* Look for xterm in path */
679 xterm_exe=mi_search_in_path("xterm");
680 if (!xterm_exe)
681 return "/usr/bin/X11/xterm";
682 }
683 return xterm_exe;
684}
685
686void mi_set_main_func(const char *name)
687{
688 free(main_func);
689 main_func=name ? strdup(name) : NULL;
690 mi_register_exit();
691}
692
693const char *mi_get_main_func()
694{
695 if (main_func)
696 return main_func;
697 return "main";
698}
699
700/**[txh]********************************************************************
701
702 Description:
703 Opens a new xterm to be used by the child process to debug.
704
705 Return: A new mi_aux_term structure, you can use gmi_end_aux_term to
706release it.
707
708***************************************************************************/
709
710mi_aux_term *gmi_start_xterm()
711{
712 char nsh[14]="/tmp/shXXXXXX";
713 char ntt[14]="/tmp/ttXXXXXX";
714 const char *xterm;
715 struct stat st;
716 int hsh, htt=-1;
717 mi_aux_term *res=NULL;
718 FILE *f;
719 pid_t pid;
720 char buf[PATH_MAX];
721
722 /* Verify we have an X terminal. */
723 xterm=mi_get_xterm_exe();
724 if (access(xterm,X_OK))
725 {
726 mi_error=MI_MISSING_XTERM;
727 return NULL;
728 }
729
730 /* Create 2 temporals. */
731 hsh=mkstemp(nsh);
732 if (hsh==-1)
733 {
734 mi_error=MI_CREATE_TEMPORAL;
735 return NULL;
736 }
737 htt=mkstemp(ntt);
738 if (htt==-1)
739 {
740 close(hsh);
741 unlink(nsh);
742 mi_error=MI_CREATE_TEMPORAL;
743 return NULL;
744 }
745 close(htt);
746 /* Create the script. */
747 f=fdopen(hsh,"w");
748 if (!f)
749 {
750 close(hsh);
751 unlink(nsh);
752 unlink(ntt);
753 mi_error=MI_CREATE_TEMPORAL;
754 return NULL;
755 }
756 fprintf(f,"#!/bin/sh\n");
757 fprintf(f,"tty > %s\n",ntt);
758 fprintf(f,"rm %s\n",nsh);
759 fprintf(f,"sleep 365d\n");
760 fclose(f);
761 /* Spawn xterm. */
762 /* Create the child. */
763 pid=fork();
764 if (pid==0)
765 {/* We are the child. */
766 char *argv[5];
767 /* Pass the control to gdb. */
768 argv[0]=(char *)mi_get_xterm_exe(); /* Is that ok? */
769 argv[1]="-e";
770 argv[2]="/bin/sh";
771 argv[3]=nsh;
772 argv[4]=0;
773 execvp(argv[0],argv);
774 /* We get here only if exec failed. */
775 unlink(nsh);
776 unlink(ntt);
777 _exit(127);
778 }
779 /* We are the parent. */
780 if (pid==-1)
781 {/* Fork failed. */
782 unlink(nsh);
783 unlink(ntt);
784 mi_error=MI_FORK;
785 return NULL;
786 }
787 /* Wait until the shell is deleted. */
788 while (stat(nsh,&st)==0)
789 usleep(1000);
790 /* Try to read the tty name. */
791 f=fopen(ntt,"rt");
792 if (f)
793 {
794 if (fgets(buf,PATH_MAX,f))
795 {
796 char *s; /* Strip the \n. */
797 for (s=buf; *s && *s!='\n'; s++);
798 *s=0;
799 res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
800 if (res)
801 {
802 res->pid=pid;
803 res->tty=strdup(buf);
804 }
805 }
806 fclose(f);
807 }
808 unlink(ntt);
809 return res;
810}
811
812void mi_free_aux_term(mi_aux_term *t)
813{
814 if (!t)
815 return;
816 free(t->tty);
817 free(t);
818}
819
820/**[txh]********************************************************************
821
822 Description:
823 Closes the auxiliar terminal and releases the allocated memory.
824
825***************************************************************************/
826
827void gmi_end_aux_term(mi_aux_term *t)
828{
829 if (!t)
830 return;
831 if (t->pid!=-1 && mi_check_running_pid(t->pid))
832 mi_kill_child(t->pid);
833 mi_free_aux_term(t);
834}
835
836/**[txh]********************************************************************
837
838 Description:
839 Forces the MI version. Currently the library can't detect it so you must
840force it manually. GDB 5.x implemented MI v1 and 6.x v2.
841
842***************************************************************************/
843
844void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
845 unsigned vMinor)
846{
847 h->version=MI_VERSION2U(vMajor,vMiddle,vMinor);
848}
849
850/**[txh]********************************************************************
851
852 Description:
853 Dis/Enables the workaround for a bug in gdb.
854
855***************************************************************************/
856
857void mi_set_workaround(unsigned wa, int enable)
858{
859 switch (wa)
860 {
861 case MI_PSYM_SEARCH:
862 disable_psym_search_workaround=enable ? 0 : 1;
863 break;
864 }
865}
866
867/**[txh]********************************************************************
868
869 Description:
870 Finds if the workaround for a bug in gdb is enabled.
871
872 Return: !=0 if enabled.
873
874***************************************************************************/
875
876int mi_get_workaround(unsigned wa)
877{
878 switch (wa)
879 {
880 case MI_PSYM_SEARCH:
881 return disable_psym_search_workaround==0;
882 }
883 return 0;
884}
885
diff --git a/pathologist/src/mi/gdbmi_data_man.c b/pathologist/src/mi/gdbmi_data_man.c
new file mode 100644
index 0000000..06e1377
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_data_man.c
@@ -0,0 +1,243 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Data manipulation.
7 Comments:
8 GDB/MI commands for the "Data manipulation" section.
9
10 @<p>
11
12@<pre>
13gdb command: Implemented?
14
15-data-disassemble Yes
16-data-evaluate-expression Yes
17-data-list-changed-registers No
18-data-list-register-names Yes
19-data-list-register-values No
20-data-read-memory No
21-display-delete N.A. (delete display)
22-display-disable N.A. (disable display)
23-display-enable N.A. (enable display)
24-display-insert N.A. (display)
25-display-list N.A. (info display)
26-environment-cd No
27-environment-directory Yes, MI v1 implementation
28-environment-path No
29@</pre>
30
31Notes: @<p>
32
331) -display* aren't implemented. You can use CLI command display, but the
34results are sent to the console. So it looks like the best is to manually
35use -data-evaluate-expression to emulate it. @<p>
36
372) GDB bug mi/1770: Affects gdb<=6.2, when you ask for the names of the
38registers you get it plus the name of the "pseudo-registers", but if you
39try to get the value of a pseudo-register you get an error saying the
40register number is invalid. I reported to gdb-patches@sources.redhat.com
41on 2004/08/25 and as I didn't get any answer I filled a bug report on
422004/09/02. The patch to fix this annoying bug is:
43
44Index: gdb/mi/mi-main.c
45===================================================================
46RCS file: /cvs/src/src/gdb/mi/mi-main.c,v
47retrieving revision 1.64
48diff -u -r1.64 mi-main.c
49--- gdb/mi/mi-main.c 3 Aug 2004 00:57:27 -0000 1.64
50+++ gdb/mi/mi-main.c 25 Aug 2004 14:12:50 -0000
51@@ -423,7 +423,7 @@
52 case, some entries of REGISTER_NAME will change depending upon
53 the particular processor being debugged.
54
55- numregs = NUM_REGS;
56+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
57
58 if (argc == 0)
59 {
60----
61
62Note I had to remove an end of comment in the patch to include it here.
63This bug forced me to create another set of functions. The only way is to
64first get the values and then the names.
65Fixed by Changelog entry:
66
672004-09-12 Salvador E. Tropea <set@users.sf.net>
68 Andrew Cagney <cagney@gnu.org>
69
70 * mi/mi-main.c (mi_cmd_data_list_changed_registers)
71 (mi_cmd_data_list_register_values)
72 (mi_cmd_data_write_register_values): Include the PSEUDO_REGS in
73 the register number computation.
74
75***************************************************************************/
76
77#include "gdbmi.h"
78
79/* Low level versions. */
80
81void mi_data_evaluate_expression(mi_h *h, const char *expression)
82{
83 mi_send(h,"-data-evaluate-expression \"%s\"\n",expression);
84}
85
86void mi_dir(mi_h *h, const char *path)
87{
88 if (h->version>=MI_VERSION2U(2,0,0))
89 {// MI v2
90 if (path)
91 mi_send(h,"-environment-directory \"%s\"\n",path);
92 else
93 mi_send(h,"-environment-directory -r\n");
94 }
95 else
96 {
97 mi_send(h,"-environment-directory %s\n",path ? path : "");
98 }
99}
100
101void mi_data_read_memory_hx(mi_h *h, const char *exp, unsigned ws,
102 unsigned c, int convAddr)
103{
104 if (convAddr)
105 mi_send(h,"-data-read-memory \"&%s\" x %d 1 %d\n",exp,ws,c);
106 else
107 mi_send(h,"-data-read-memory \"%s\" x %d 1 %d\n",exp,ws,c);
108}
109
110void mi_data_disassemble_se(mi_h *h, const char *start, const char *end,
111 int mode)
112{
113 mi_send(h,"-data-disassemble -s \"%s\" -e \"%s\" -- %d\n",start,end,mode);
114}
115
116void mi_data_disassemble_fl(mi_h *h, const char *file, int line, int lines,
117 int mode)
118{
119 mi_send(h,"-data-disassemble -f \"%s\" -l %d -n %d -- %d\n",file,line,lines,
120 mode);
121}
122
123void mi_data_list_register_names(mi_h *h)
124{
125 mi_send(h,"-data-list-register-names\n");
126}
127
128void mi_data_list_register_names_l(mi_h *h, mi_chg_reg *l)
129{
130 mi_send(h,"-data-list-register-names ");
131 while (l)
132 {
133 mi_send(h,"%d ",l->reg);
134 l=l->next;
135 }
136 mi_send(h,"\n");
137}
138
139void mi_data_list_changed_registers(mi_h *h)
140{
141 mi_send(h,"-data-list-changed-registers\n");
142}
143
144void mi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l)
145{
146 mi_send(h,"-data-list-register-values %c ",mi_format_enum_to_char(fmt));
147 while (l)
148 {
149 mi_send(h,"%d ",l->reg);
150 l=l->next;
151 }
152 mi_send(h,"\n");
153}
154
155/* High level versions. */
156
157/**[txh]********************************************************************
158
159 Description:
160 Evaluate an expression. Returns a parsed tree.
161
162 Command: -data-evaluate-expression
163 Return: The resulting value (as plain text) or NULL on error.
164
165***************************************************************************/
166
167char *gmi_data_evaluate_expression(mi_h *h, const char *expression)
168{
169 mi_data_evaluate_expression(h,expression);
170 return mi_res_value(h);
171}
172
173/**[txh]********************************************************************
174
175 Description:
176 Path for sources. You must use it to indicate where are the sources for
177the program to debug. Only the MI v1 implementation is available.
178
179 Command: -environment-directory
180 Return: !=0 OK
181
182***************************************************************************/
183
184int gmi_dir(mi_h *h, const char *path)
185{
186 mi_dir(h,path);
187 return mi_res_simple_done(h);
188}
189
190int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
191 unsigned char *dest, int *na, int convAddr,
192 unsigned long *addr)
193{
194 mi_data_read_memory_hx(h,exp,1,size,convAddr);
195 return mi_get_read_memory(h,dest,1,na,addr);
196}
197
198mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
199 const char *end, int mode)
200{
201 mi_data_disassemble_se(h,start,end,mode);
202 return mi_get_asm_insns(h);
203}
204
205mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
206 int lines, int mode)
207{
208 mi_data_disassemble_fl(h,file,line,lines,mode);
209 return mi_get_asm_insns(h);
210}
211
212// Affected by gdb bug mi/1770
213mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many)
214{
215 mi_data_list_register_names(h);
216 return mi_get_list_registers(h,how_many);
217}
218
219int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l)
220{
221 mi_data_list_register_names_l(h,l);
222 return mi_get_list_registers_l(h,l);
223}
224
225mi_chg_reg *gmi_data_list_changed_registers(mi_h *h)
226{
227 mi_error=MI_OK;
228 mi_data_list_changed_registers(h);
229 return mi_get_list_changed_regs(h);
230}
231
232int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l)
233{
234 mi_data_list_register_values(h,fmt,l);
235 return mi_get_reg_values(h,l);
236}
237
238mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many)
239{
240 mi_data_list_register_values(h,fmt,NULL);
241 return mi_get_reg_values_l(h,how_many);
242}
243
diff --git a/pathologist/src/mi/gdbmi_error.c b/pathologist/src/mi/gdbmi_error.c
new file mode 100644
index 0000000..abb20f6
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_error.c
@@ -0,0 +1,38 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Error.
7 Comment:
8 Translates error numbers into messages.
9
10***************************************************************************/
11
12#include "gdbmi.h"
13
14static
15const char *error_strs[]=
16{
17 "Ok",
18 "Out of memory",
19 "Pipe creation",
20 "Fork failed",
21 "GDB not running",
22 "Parser failed",
23 "Unknown asyn response",
24 "Unknown result response",
25 "Error from gdb",
26 "Time out in gdb response",
27 "GDB suddenly died",
28 "Can't execute X terminal",
29 "Failed to create temporal",
30 "Can't execute the debugger"
31};
32
33const char *mi_get_error_str()
34{
35 if (mi_error<0 || mi_error>MI_LAST_ERROR)
36 return "Unknown";
37 return error_strs[mi_error];
38}
diff --git a/pathologist/src/mi/gdbmi_get_free_pty.c b/pathologist/src/mi/gdbmi_get_free_pty.c
new file mode 100644
index 0000000..4274c78
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_get_free_pty.c
@@ -0,0 +1,132 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: pseudo terminal
7 Comments:
8 Helper to find a free pseudo terminal. Use this if you need to manage
9 input *and* output to the target process. If you just need output then
10 define a handler for target output stream records (assuming that this
11 is working for your particular version of gdb).
12 Usage:
13
14 mi_pty *pty = gmi_look_for_free_pty();
15 if (pty) gmi_target_terminal(mih, pty->slave);
16 ...
17 * reading from pty->master will get stdout from target *
18 * writing to pty->master will send to target stdin *
19
20 Note: Contributed by Greg Watson (gwatson lanl gov)
21
22***************************************************************************/
23
24#define _GNU_SOURCE
25#include <string.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <sys/ioctl.h>
30
31#include "gdbmi.h"
32
33/**[txh]********************************************************************
34
35 Description:
36 Look for a free and usable pseudo terminal. Low level, use
37 gmi_look_for_free_pty().
38
39 Return: A file descriptor connected to the master pty and the name of the slave device, or <0 on error.
40
41***************************************************************************/
42
43#ifdef __APPLE__
44
45#include <util.h>
46
47int mi_look_for_free_pty(int *master, char **slave)
48{
49 int fdmaster;
50 int fdslave;
51 static char name[BUFSIZ];
52
53 if (openpty(&fdmaster,&fdslave,name,NULL,NULL)<0)
54 return -1;
55
56 (void)close(fdslave); /* this will be reopened by gdb */
57 *master=fdmaster;
58 *slave =name;
59
60 return 0;
61}
62
63#elif defined(__linux__)
64
65int mi_look_for_free_pty(int *master, char **slave)
66{
67 if ((*master=open("/dev/ptmx",O_RDWR))<0)
68 return -1;
69 if (grantpt(*master)<0 || unlockpt(*master)<0)
70 return -1;
71 *slave = ptsname(*master);
72
73 return 0;
74}
75
76#else /* undefined o/s */
77
78int mi_look_for_free_pty(int *master, char **slave)
79{
80 return -1;
81}
82#endif
83
84/**[txh]********************************************************************
85
86 Description:
87 Look for a free and usable pseudo terminal to be used by the child.
88
89 Return: A new mi_pty structure, you can use gmi_end_pty to
90release it.
91
92***************************************************************************/
93
94mi_pty *gmi_look_for_free_pty()
95{
96 int master;
97 char *slave;
98 int pty=mi_look_for_free_pty(&master,&slave);
99 mi_pty *res;
100
101 if (pty<0)
102 return NULL;
103 res=(mi_pty *)malloc(sizeof(mi_pty));
104 if (!res)
105 return NULL;
106 res->slave=strdup(slave);
107 res->master=master;
108 return res;
109}
110
111void mi_free_pty(mi_pty *p)
112{
113 if (!p)
114 return;
115 free(p->slave);
116 free(p);
117}
118
119/**[txh]********************************************************************
120
121 Description:
122 Closes the pseudo termial master and releases the allocated memory.
123
124***************************************************************************/
125
126void gmi_end_pty(mi_pty *p)
127{
128 if (!p)
129 return;
130 close(p->master);
131 mi_free_pty(p);
132}
diff --git a/pathologist/src/mi/gdbmi_get_free_vt.c b/pathologist/src/mi/gdbmi_get_free_vt.c
new file mode 100644
index 0000000..25e5e75
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_get_free_vt.c
@@ -0,0 +1,156 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Linux VT.
7 Comments:
8 Helper to find a free VT. That's 100% Linux specific.@p
9 The code comes from "lconsole.c" from Allegro project and was originally
10created by Marek Habersack and then modified by George Foot. I addapted it
11to my needs and changed license from giftware to GPL.@p
12
13***************************************************************************/
14
15#define _GNU_SOURCE
16#include <string.h>
17#include <stdio.h>
18#include <unistd.h>
19#include <fcntl.h>
20#include <sys/ioctl.h>
21#ifdef __APPLE__
22#include <util.h>
23#endif /* __APPLE__ */
24
25#include "gdbmi.h"
26
27#if !defined(__linux__)
28
29int mi_look_for_free_vt()
30{
31 return -1;
32}
33
34mi_aux_term *gmi_look_for_free_vt()
35{
36 return NULL;
37}
38
39#else
40
41#include <linux/vt.h>
42
43/**[txh]********************************************************************
44
45 Description:
46 Look for a free and usable Linux VT. Low level, use
47@x{gmi_look_for_free_vt}.
48
49 Return: The VT number or <0 on error.
50
51***************************************************************************/
52
53int mi_look_for_free_vt()
54{/* Code from Allegro. */
55 int tty, console_fd, fd;
56 unsigned short mask;
57 char tty_name[16];
58 struct vt_stat vts;
59
60 /* Now we need to find a VT we can use. It must be readable and
61 * writable by us, if we're not setuid root. VT_OPENQRY itself
62 * isn't too useful because it'll only ever come up with one
63 * suggestion, with no guarrantee that we actually have access
64 * to it.
65 *
66 * At some stage I think this is a candidate for config
67 * file overriding, but for now we'll stat the first N consoles
68 * to see which ones we can write to (hopefully at least one!),
69 * so that we can use that one to do ioctls. We used to use
70 * /dev/console for that purpose but it looks like it's not
71 * always writable by enough people.
72 *
73 * Having found and opened a writable device, we query the state
74 * of the first sixteen (fifteen really) consoles, and try
75 * opening each unused one in turn.
76 */
77
78 console_fd=open("/dev/console",O_WRONLY);
79 if (console_fd<0)
80 {
81 int n;
82 /* Try some ttys instead... */
83 for (n=1; n<=24; n++)
84 {
85 snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",n);
86 console_fd=open(tty_name,O_WRONLY);
87 if (console_fd>=0)
88 break;
89 }
90 if (n>24)
91 return -1;
92 }
93
94 /* Get the state of the console -- in particular, the free VT field */
95 if (ioctl(console_fd,VT_GETSTATE,&vts)) {
96 close(console_fd);
97 return -2;
98 }
99 close(console_fd);
100
101 /* We attempt to set our euid to 0; if we were run with euid 0 to
102 * start with, we'll be able to do this now. Otherwise, we'll just
103 * ignore the error returned since it might not be a problem if the
104 * ttys we look at are owned by the user running the program. */
105 seteuid(0);
106
107 /* tty0 is not really a console, so start counting at 2. */
108 fd=-1;
109 for (tty=1, mask=2; mask; tty++, mask<<=1)
110 if (!(vts.v_state & mask))
111 {
112 snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",tty);
113 fd=open(tty_name,O_RDWR);
114 if (fd!=-1)
115 {
116 close(fd);
117 break;
118 }
119 }
120
121 seteuid(getuid());
122
123 if (!mask)
124 return -3;
125
126 return tty;
127}
128
129/**[txh]********************************************************************
130
131 Description:
132 Look for a free and usable Linux VT to be used by the child.
133
134 Return: A new mi_aux_term structure, you can use @x{gmi_end_aux_term} to
135release it.
136
137***************************************************************************/
138
139mi_aux_term *gmi_look_for_free_vt()
140{
141 int ret;
142 int vt=mi_look_for_free_vt();
143 mi_aux_term *res;
144
145 if (vt<0)
146 return NULL;
147 res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
148 if (!res)
149 return NULL;
150 res->pid=-1;
151 ret = asprintf(&res->tty,"/dev/tty%d",vt);
152 return res;
153}
154
155#endif
156
diff --git a/pathologist/src/mi/gdbmi_misc.c b/pathologist/src/mi/gdbmi_misc.c
new file mode 100644
index 0000000..51088a7
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_misc.c
@@ -0,0 +1,118 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Miscellaneous commands.
7 Comments:
8 GDB/MI commands for the "Miscellaneous Commands" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12
13-gdb-exit Yes
14-gdb-set Yes
15-gdb-show Yes
16-gdb-version Yes
17@</pre>
18
19GDB Bug workaround for "-gdb-show architecture": gdb 6.1 and olders doesn't
20report it in "value", but they give the output of "show architecture". In
216.4 we observed that not even a clue is reported. So now we always use
22"show architecture".
23
24***************************************************************************/
25
26#include <string.h>
27#include "gdbmi.h"
28
29/* Low level versions. */
30
31void mi_gdb_exit(mi_h *h)
32{
33 mi_send(h,"-gdb-exit\n");
34}
35
36void mi_gdb_version(mi_h *h)
37{
38 mi_send(h,"-gdb-version\n");
39}
40
41void mi_gdb_set(mi_h *h, const char *var, const char *val)
42{
43 mi_send(h,"-gdb-set %s %s\n",var,val);
44}
45
46void mi_gdb_show(mi_h *h, const char *var)
47{
48 if (strcmp(var,"architecture")==0)
49 mi_send(h,"show %s\n",var);
50 else
51 mi_send(h,"-gdb-show %s\n",var);
52}
53
54/* High level versions. */
55
56/**[txh]********************************************************************
57
58 Description:
59 Exit gdb killing the child is it is running.
60
61 Command: -gdb-exit
62
63***************************************************************************/
64
65void gmi_gdb_exit(mi_h *h)
66{
67 mi_gdb_exit(h);
68 mi_res_simple_exit(h);
69}
70
71/**[txh]********************************************************************
72
73 Description:
74 Send the version to the console.
75
76 Command: -gdb-version
77 Return: !=0 OK
78
79***************************************************************************/
80
81int gmi_gdb_version(mi_h *h)
82{
83 mi_gdb_version(h);
84 return mi_res_simple_done(h);
85}
86
87/**[txh]********************************************************************
88
89 Description:
90 Set a gdb variable.
91
92 Command: -gdb-set
93 Return: !=0 OK
94
95***************************************************************************/
96
97int gmi_gdb_set(mi_h *h, const char *var, const char *val)
98{
99 mi_gdb_set(h,var,val);
100 return mi_res_simple_done(h);
101}
102
103/**[txh]********************************************************************
104
105 Description:
106 Get a gdb variable.
107
108 Command: -gdb-show
109 Return: The current value of the variable or NULL on error.
110
111***************************************************************************/
112
113char *gmi_gdb_show(mi_h *h, const char *var)
114{
115 mi_gdb_show(h,var);
116 return mi_res_value(h);
117}
118
diff --git a/pathologist/src/mi/gdbmi_parse.c b/pathologist/src/mi/gdbmi_parse.c
new file mode 100644
index 0000000..d30bd22
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_parse.c
@@ -0,0 +1,1927 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2007 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Parser.
7 Comments:
8 Parses the output of gdb. It basically converts the text from gdb into a
9tree (could be a complex one) that we can easily interpret using C code.
10
11***************************************************************************/
12
13#include <ctype.h>
14#include <string.h>
15#include <assert.h>
16#include "gdbmi.h"
17
18mi_results *mi_get_result(const char *str, const char **end);
19int mi_get_value(mi_results *r, const char *str, const char **end);
20
21
22/* GDB BUG!!!! I got:
23^error,msg="Problem parsing arguments: data-evaluate-expression ""1+2"""
24Afects gdb 2002-04-01-cvs and 6.1.1 for sure.
25That's an heuristical workaround.
26*/
27static inline
28int EndOfStr(const char *s)
29{
30 if (*s=='"')
31 {
32 s++;
33 return !*s || *s==',' || *s==']' || *s=='}';
34 }
35 return 0;
36}
37
38int mi_get_cstring_r(mi_results *r, const char *str, const char **end)
39{
40 const char *s;
41 char *d;
42 int len;
43
44 if (*str!='"')
45 {
46 mi_error=MI_PARSER;
47 return 0;
48 }
49 str++;
50 /* Meassure. */
51 for (s=str, len=0; *s && !EndOfStr(s); s++)
52 {
53 if (!*s) {
54 mi_error = MI_PARSER;
55 return 0;
56 }
57 if (*s=='\\')
58 s++;
59 len++;
60 }
61 /* Copy. */
62 r->type=t_const;
63 d=r->v.cstr=mi_malloc(len+1);
64 if (!r->v.cstr)
65 return 0;
66 for (s=str; *s && !EndOfStr(s); s++, d++)
67 {
68 if (*s=='\\')
69 {
70 s++;
71 switch (*s)
72 {
73 case 'n':
74 *d='\n';
75 break;
76 case 't':
77 *d='\t';
78 break;
79 default:
80 *d=*s;
81 }
82 }
83 else
84 *d=*s;
85 }
86 *d=0;
87 if (end)
88 *end=s+1;
89
90 return 1;
91}
92
93/* TODO: What's a valid variable name?
94 I'll assume a-zA-Z0-9_- */
95//inline
96int mi_is_var_name_char(char c)
97{
98 return isalnum(c) || c=='-' || c=='_';
99}
100
101char *mi_get_var_name(const char *str, const char **end)
102{
103 const char *s;
104 char *r;
105 int l;
106 /* Meassure. */
107 for (s=str; *s && mi_is_var_name_char(*s); s++);
108 if (*s!='=')
109 {
110 mi_error=MI_PARSER;
111 return NULL;
112 }
113 /* Allocate. */
114 l=s-str;
115 r=mi_malloc(l+1);
116 /* Copy. */
117 if (NULL != r) {
118 memcpy(r,str,l);
119 r[l]=0;
120 }
121 if (end)
122 *end=s+1;
123 return r;
124}
125
126
127int mi_get_list_res(mi_results *r, const char *str, const char **end, char closeC)
128{
129 mi_results *last_r, *rs;
130
131 last_r=NULL;
132 do
133 {
134 rs=mi_get_result(str,&str);
135 if (last_r)
136 last_r->next=rs;
137 else
138 r->v.rs=rs;
139 last_r=rs;
140 if (*str==closeC)
141 {
142 *end=str+1;
143 return 1;
144 }
145 if (*str!=',')
146 break;
147 str++;
148 }
149 while (1);
150
151 mi_error=MI_PARSER;
152 return 0;
153}
154
155#ifdef __APPLE__
156int mi_get_tuple_val(mi_results *r, const char *str, const char **end)
157{
158 mi_results *last_r, *rs;
159
160 last_r=NULL;
161 do
162 {
163 rs=mi_alloc_results();
164 if (!rs || !mi_get_value(rs,str,&str))
165 {
166 mi_free_results(rs);
167 return 0;
168 }
169 /* Note that rs->var is NULL, that indicates that's just a value and not
170 a result. */
171 if (last_r)
172 last_r->next=rs;
173 else
174 r->v.rs=rs;
175 last_r=rs;
176 if (*str=='}')
177 {
178 *end=str+1;
179 return 1;
180 }
181 if (*str!=',')
182 break;
183 str++;
184 }
185 while (1);
186
187 mi_error=MI_PARSER;
188 return 0;
189}
190#endif /* __APPLE__ */
191
192int mi_get_tuple(mi_results *r, const char *str, const char **end)
193{
194 if (*str!='{')
195 {
196 mi_error=MI_PARSER;
197 return 0;
198 }
199 r->type=t_tuple;
200 str++;
201 if (*str=='}')
202 {/* Special case: empty tuple */
203 *end=str+1;
204 return 1;
205 }
206 #ifdef __APPLE__
207 if (mi_is_var_name_char(*str))
208 return mi_get_list_res(r,str,end,'}');
209 return mi_get_tuple_val(r,str,end);
210 #else /* __APPLE__ */
211 return mi_get_list_res(r,str,end,'}');
212 #endif /* __APPLE__ */
213}
214
215int mi_get_list_val(mi_results *r, const char *str, const char **end)
216{
217 mi_results *last_r, *rs;
218
219 last_r=NULL;
220 do
221 {
222 rs=mi_alloc_results();
223 if (!rs || !mi_get_value(rs,str,&str))
224 {
225 mi_free_results(rs);
226 return 0;
227 }
228 /* Note that rs->var is NULL, that indicates that's just a value and not
229 a result. */
230 if (last_r)
231 last_r->next=rs;
232 else
233 r->v.rs=rs;
234 last_r=rs;
235 if (*str==']')
236 {
237 *end=str+1;
238 return 1;
239 }
240 if (*str!=',')
241 break;
242 str++;
243 }
244 while (1);
245
246 mi_error=MI_PARSER;
247 return 0;
248}
249
250int mi_get_list(mi_results *r, const char *str, const char **end)
251{
252 if (*str!='[')
253 {
254 mi_error=MI_PARSER;
255 return 0;
256 }
257 r->type=t_list;
258 str++;
259 if (*str==']')
260 {/* Special case: empty list */
261 *end=str+1;
262 return 1;
263 }
264 /* Comment: I think they could choose () for values. Is confusing in this way. */
265 if (mi_is_var_name_char(*str))
266 return mi_get_list_res(r,str,end,']');
267 return mi_get_list_val(r,str,end);
268}
269
270int mi_get_value(mi_results *r, const char *str, const char **end)
271{
272 switch (str[0])
273 {
274 case '"':
275 return mi_get_cstring_r(r,str,end);
276 case '{':
277 return mi_get_tuple(r,str,end);
278 case '[':
279 return mi_get_list(r,str,end);
280 }
281 mi_error=MI_PARSER;
282 return 0;
283}
284
285mi_results *mi_get_result(const char *str, const char **end)
286{
287 char *var;
288 mi_results *r;
289
290 var=mi_get_var_name(str,&str);
291 if (!var)
292 return NULL;
293
294 r=mi_alloc_results();
295 if (!r)
296 {
297 free(var);
298 return NULL;
299 }
300 r->var=var;
301
302 if (!mi_get_value(r,str,end))
303 {
304 mi_free_results(r);
305 return NULL;
306 }
307
308 return r;
309}
310
311mi_output *mi_get_results_alone(mi_output *r,const char *str)
312{
313 mi_results *last_r, *rs;
314
315 /* * results */
316 last_r=NULL;
317 do
318 {
319 if (!*str)
320 return r;
321 if (*str!=',')
322 {
323 mi_error=MI_PARSER;
324 break;
325 }
326 str++;
327 rs=mi_get_result(str,&str);
328 if (!rs)
329 break;
330 if (!last_r)
331 r->c=rs;
332 else
333 last_r->next=rs;
334 last_r=rs;
335 }
336 while (1);
337 mi_free_output(r);
338 return NULL;
339}
340
341mi_output *mi_parse_result_record(mi_output *r,const char *str)
342{
343 r->type=MI_T_RESULT_RECORD;
344
345 /* Solve the result-class. */
346 if (strncmp(str,"done",4)==0)
347 {
348 str+=4;
349 r->tclass=MI_CL_DONE;
350 }
351 else if (strncmp(str,"running",7)==0)
352 {
353 str+=7;
354 r->tclass=MI_CL_RUNNING;
355 }
356 else if (strncmp(str,"connected",9)==0)
357 {
358 str+=9;
359 r->tclass=MI_CL_CONNECTED;
360 }
361 else if (strncmp(str,"error",5)==0)
362 {
363 str+=5;
364 r->tclass=MI_CL_ERROR;
365 }
366 else if (strncmp(str,"exit",4)==0)
367 {
368 str+=4;
369 r->tclass=MI_CL_EXIT;
370 }
371 else
372 {
373 mi_error=MI_UNKNOWN_RESULT;
374 return NULL;
375 }
376
377 return mi_get_results_alone(r,str);
378}
379
380mi_output *mi_parse_asyn(mi_output *r,const char *str)
381{
382 r->type=MI_T_OUT_OF_BAND;
383 r->stype=MI_ST_ASYNC;
384 /* async-class. */
385 if (strncmp(str,"stopped",7)==0)
386 {
387 r->tclass=MI_CL_STOPPED;
388 str+=7;
389 return mi_get_results_alone(r,str);
390 }
391 if (strncmp(str,"download",8)==0)
392 {
393 r->tclass=MI_CL_DOWNLOAD;
394 str+=8;
395 return mi_get_results_alone(r,str);
396 }
397 mi_error=MI_UNKNOWN_ASYNC;
398 mi_free_output(r);
399 return NULL;
400}
401
402mi_output *mi_parse_exec_asyn(mi_output *r,const char *str)
403{
404 r->sstype=MI_SST_EXEC;
405 return mi_parse_asyn(r,str);
406}
407
408mi_output *mi_parse_status_asyn(mi_output *r,const char *str)
409{
410 r->sstype=MI_SST_STATUS;
411 return mi_parse_asyn(r,str);
412}
413
414mi_output *mi_parse_notify_asyn(mi_output *r,const char *str)
415{
416 r->sstype=MI_SST_NOTIFY;
417 return mi_parse_asyn(r,str);
418}
419
420mi_output *mi_console(mi_output *r,const char *str)
421{
422 r->type=MI_T_OUT_OF_BAND;
423 r->stype=MI_ST_STREAM;
424 r->c=mi_alloc_results();
425 if (!r->c || !mi_get_cstring_r(r->c,str,NULL))
426 {
427 mi_free_output(r);
428 return NULL;
429 }
430 return r;
431}
432
433mi_output *mi_console_stream(mi_output *r,const char *str)
434{
435 r->sstype=MI_SST_CONSOLE;
436 return mi_console(r,str);
437}
438
439mi_output *mi_target_stream(mi_output *r,const char *str)
440{
441 r->sstype=MI_SST_TARGET;
442 return mi_console(r,str);
443}
444
445mi_output *mi_log_stream(mi_output *r,const char *str)
446{
447 r->sstype=MI_SST_LOG;
448 return mi_console(r,str);
449}
450
451mi_output *mi_parse_gdb_output(const char *str)
452{
453 char type=str[0];
454
455 mi_output *r=mi_alloc_output();
456 if (!r)
457 {
458 mi_error=MI_OUT_OF_MEMORY;
459 return NULL;
460 }
461 str++;
462 switch (type)
463 {
464 case '^':
465 return mi_parse_result_record(r,str);
466 case '*':
467 return mi_parse_exec_asyn(r,str);
468 case '+':
469 return mi_parse_status_asyn(r,str);
470 case '=':
471 return mi_parse_notify_asyn(r,str);
472 case '~':
473 return mi_console_stream(r,str);
474 case '@':
475 return mi_target_stream(r,str);
476 case '&':
477 return mi_log_stream(r,str);
478 }
479 mi_error=MI_PARSER;
480 return NULL;
481}
482
483mi_output *mi_get_rrecord(mi_output *r)
484{
485 if (!r)
486 return NULL;
487 while (r)
488 {
489 if (r->type==MI_T_RESULT_RECORD)
490 return r;
491 r=r->next;
492 }
493 return r;
494}
495
496mi_results *mi_get_var_r(mi_results *r, const char *var)
497{
498 while (r)
499 {
500 if (strcmp(r->var,var)==0)
501 return r;
502 r=r->next;
503 }
504 return NULL;
505}
506
507mi_results *mi_get_var(mi_output *res, const char *var)
508{
509 if (!res)
510 return NULL;
511 return mi_get_var_r(res->c,var);
512}
513
514int mi_get_async_stop_reason(mi_output *r, char **reason)
515{
516 int found_stopped=0;
517
518 *reason=NULL;
519 while (r)
520 {
521 if (r->type==MI_T_RESULT_RECORD && r->tclass==MI_CL_ERROR)
522 {
523 if (r->c->type==t_const)
524 *reason=r->c->v.cstr;
525 return 0;
526 }
527 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
528 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
529 {
530 mi_results *p=r->c;
531 found_stopped=1;
532 while (p)
533 {
534 if (strcmp(p->var,"reason")==0)
535 {
536 *reason=p->v.cstr;
537 return 1;
538 }
539 p=p->next;
540 }
541 }
542 r=r->next;
543 }
544 if (*reason==NULL && found_stopped)
545 {
546 *reason=strdup("unknown (temp bkpt?)");
547 return 1;
548 }
549 return 0;
550}
551
552mi_frames *mi_get_async_frame(mi_output *r)
553{
554 while (r)
555 {
556 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
557 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
558 {
559 mi_results *p=r->c;
560 while (p)
561 {
562 if (strcmp(p->var,"frame")==0)
563 return mi_parse_frame(p->v.rs);
564 p=p->next;
565 }
566 }
567 r=r->next;
568 }
569 return NULL;
570}
571
572int mi_res_simple(mi_h *h, int tclass, int accert_ret)
573{
574 mi_output *r, *res;
575 int ret=0;
576
577 r=mi_get_response_blk(h);
578 res=mi_get_rrecord(r);
579
580 if (res)
581 ret=res->tclass==tclass;
582 mi_free_output(r);
583
584 return ret;
585}
586
587
588int mi_res_simple_done(mi_h *h)
589{
590 return mi_res_simple(h,MI_CL_DONE,0);
591}
592
593int mi_res_simple_exit(mi_h *h)
594{
595 return mi_res_simple(h,MI_CL_EXIT,1);
596}
597
598int mi_res_simple_running(mi_h *h)
599{
600 return mi_res_simple(h,MI_CL_RUNNING,0);
601}
602
603int mi_res_simple_connected(mi_h *h)
604{
605 return mi_res_simple(h,MI_CL_CONNECTED,0);
606}
607
608mi_results *mi_res_var(mi_h *h, const char *var, int tclass)
609{
610 mi_output *r, *res;
611 mi_results *the_var=NULL;
612
613 r=mi_get_response_blk(h);
614 /* All the code that follows is "NULL" tolerant. */
615 /* Look for the result-record. */
616 res=mi_get_rrecord(r);
617 /* Look for the desired var. */
618 if (res && res->tclass==tclass)
619 the_var=mi_get_var(res,var);
620 /* Release all but the one we want. */
621 mi_free_output_but(r,NULL,the_var);
622 return the_var;
623}
624
625mi_results *mi_res_done_var(mi_h *h, const char *var)
626{
627 return mi_res_var(h,var,MI_CL_DONE);
628}
629
630mi_frames *mi_parse_frame(mi_results *c)
631{
632 mi_frames *res=mi_alloc_frames();
633 char *end;
634
635 if (res)
636 {
637 while (c)
638 {
639 if (c->type==t_const)
640 {
641 if (strcmp(c->var,"level")==0)
642 res->level=atoi(c->v.cstr);
643 else if (strcmp(c->var,"addr")==0)
644 res->addr=(void *)strtoul(c->v.cstr,&end,0);
645 else if (strcmp(c->var,"func")==0)
646 {
647 res->func=c->v.cstr;
648 c->v.cstr=NULL;
649 }
650 else if (strcmp(c->var,"file")==0)
651 {
652 res->file=c->v.cstr;
653 c->v.cstr=NULL;
654 }
655 else if (strcmp(c->var,"from")==0)
656 {
657 res->from=c->v.cstr;
658 c->v.cstr=NULL;
659 }
660 else if (strcmp(c->var,"line")==0)
661 res->line=atoi(c->v.cstr);
662 }
663 else if (c->type==t_list && strcmp(c->var,"args")==0)
664 {
665 res->args=c->v.rs;
666 c->v.rs=NULL;
667 }
668 c=c->next;
669 }
670 }
671 return res;
672}
673
674mi_frames *mi_res_frame(mi_h *h)
675{
676 mi_results *r=mi_res_done_var(h,"frame");
677 mi_frames *f=NULL;
678
679 if (r && r->type==t_tuple)
680 f=mi_parse_frame(r->v.rs);
681 mi_free_results(r);
682 return f;
683}
684
685mi_frames *mi_res_frames_array(mi_h *h, const char *var)
686{
687 mi_results *r=mi_res_done_var(h,var), *c;
688 mi_frames *res=NULL, *nframe, *last=NULL;
689
690 if (!r)
691 return NULL;
692#ifdef __APPLE__
693 if (r->type!=t_list && r->type!=t_tuple)
694#else
695 if (r->type!=t_list)
696#endif
697 {
698 mi_free_results(r);
699 return NULL;
700 }
701 c=r->v.rs;
702 while (c)
703 {
704 if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
705 {
706 nframe=mi_parse_frame(c->v.rs);
707 if (nframe)
708 {
709 if (!last)
710 res=nframe;
711 else
712 last->next=nframe;
713 last=nframe;
714 }
715 }
716 c=c->next;
717 }
718 mi_free_results(r);
719 return res;
720}
721
722mi_frames *mi_res_frames_list(mi_h *h)
723{
724 mi_output *r, *res;
725 mi_frames *ret=NULL, *nframe, *last=NULL;
726 mi_results *c;
727
728 r=mi_get_response_blk(h);
729 res=mi_get_rrecord(r);
730 if (res && res->tclass==MI_CL_DONE)
731 {
732 c=res->c;
733 while (c)
734 {
735 if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
736 {
737 nframe=mi_parse_frame(c->v.rs);
738 if (nframe)
739 {
740 if (!last)
741 ret=nframe;
742 else
743 last->next=nframe;
744 last=nframe;
745 }
746 }
747 c=c->next;
748 }
749 }
750 mi_free_output(r);
751 return ret;
752}
753
754int mi_get_thread_ids(mi_output *res, int **list)
755{
756 mi_results *vids, *lids;
757 int ids=-1, i;
758
759 *list=NULL;
760 vids=mi_get_var(res,"number-of-threads");
761 lids=mi_get_var(res,"thread-ids");
762 if (vids && vids->type==t_const &&
763 lids && lids->type==t_tuple)
764 {
765 ids=atoi(vids->v.cstr);
766 if (ids)
767 {
768 int *lst;
769 lst=(int *)mi_calloc(ids,sizeof(int));
770 if (lst)
771 {
772 lids=lids->v.rs;
773 i=0;
774 while (lids)
775 {
776 if (strcmp(lids->var,"thread-id")==0 && lids->type==t_const)
777 lst[i++]=atoi(lids->v.cstr);
778 lids=lids->next;
779 }
780 *list=lst;
781 }
782 else
783 ids=-1;
784 }
785 }
786 return ids;
787}
788
789int mi_res_thread_ids(mi_h *h, int **list)
790{
791 mi_output *r, *res;
792 int ids=-1;
793
794 r=mi_get_response_blk(h);
795 res=mi_get_rrecord(r);
796 if (res && res->tclass==MI_CL_DONE)
797 ids=mi_get_thread_ids(res,list);
798 mi_free_output(r);
799 return ids;
800}
801
802enum mi_gvar_lang mi_lang_str_to_enum(const char *lang)
803{
804 enum mi_gvar_lang lg=lg_unknown;
805
806 if (strcmp(lang,"C")==0)
807 lg=lg_c;
808 else if (strcmp(lang,"C++")==0)
809 lg=lg_cpp;
810 else if (strcmp(lang,"Java")==0)
811 lg=lg_java;
812
813 return lg;
814}
815
816const char *mi_lang_enum_to_str(enum mi_gvar_lang lang)
817{
818 const char *lg;
819
820 switch (lang)
821 {
822 case lg_c:
823 lg="C";
824 break;
825 case lg_cpp:
826 lg="C++";
827 break;
828 case lg_java:
829 lg="Java";
830 break;
831 /*case lg_unknown:*/
832 default:
833 lg="unknown";
834 break;
835 }
836 return lg;
837}
838
839enum mi_gvar_fmt mi_format_str_to_enum(const char *format)
840{
841 enum mi_gvar_fmt fmt=fm_natural;
842
843 if (strcmp(format,"binary")==0)
844 fmt=fm_binary;
845 else if (strcmp(format,"decimal")==0)
846 fmt=fm_decimal;
847 else if (strcmp(format,"hexadecimal")==0)
848 fmt=fm_hexadecimal;
849 else if (strcmp(format,"octal")==0)
850 fmt=fm_octal;
851
852 return fmt;
853}
854
855const char *mi_format_enum_to_str(enum mi_gvar_fmt format)
856{
857 const char *fmt;
858
859 switch (format)
860 {
861 case fm_natural:
862 fmt="natural";
863 break;
864 case fm_binary:
865 fmt="binary";
866 break;
867 case fm_decimal:
868 fmt="decimal";
869 break;
870 case fm_hexadecimal:
871 fmt="hexadecimal";
872 break;
873 case fm_octal:
874 fmt="octal";
875 break;
876 case fm_raw:
877 fmt="raw";
878 break;
879 default:
880 fmt="unknown";
881 }
882 return fmt;
883}
884
885char mi_format_enum_to_char(enum mi_gvar_fmt format)
886{
887 char fmt;
888
889 switch (format)
890 {
891 case fm_natural:
892 fmt='N';
893 break;
894 case fm_binary:
895 fmt='t';
896 break;
897 case fm_decimal:
898 fmt='d';
899 break;
900 case fm_hexadecimal:
901 fmt='x';
902 break;
903 case fm_octal:
904 fmt='o';
905 break;
906 case fm_raw:
907 fmt='r';
908 break;
909 default:
910 fmt=' ';
911 }
912 return fmt;
913}
914
915mi_gvar *mi_get_gvar(mi_output *o, mi_gvar *cur, const char *expression)
916{
917 mi_results *r;
918 mi_gvar *res=cur ? cur : mi_alloc_gvar();
919 int l;
920
921 if (!res)
922 return res;
923 r=o->c;
924 if (expression)
925 res->exp=strdup(expression);
926 while (r)
927 {
928 if (r->type==t_const)
929 {
930 if (strcmp(r->var,"name")==0)
931 {
932 free(res->name);
933 res->name=r->v.cstr;
934 r->v.cstr=NULL;
935 }
936 else if (strcmp(r->var,"numchild")==0)
937 {
938 res->numchild=atoi(r->v.cstr);
939 }
940 else if (strcmp(r->var,"type")==0)
941 {
942 free(res->type);
943 res->type=r->v.cstr;
944 r->v.cstr=NULL;
945 l=strlen(res->type);
946 if (l && res->type[l-1]=='*')
947 res->ispointer=1;
948 }
949 else if (strcmp(r->var,"lang")==0)
950 {
951 res->lang=mi_lang_str_to_enum(r->v.cstr);
952 }
953 else if (strcmp(r->var,"exp")==0)
954 {
955 free(res->exp);
956 res->exp=r->v.cstr;
957 r->v.cstr=NULL;
958 }
959 else if (strcmp(r->var,"format")==0)
960 {
961 res->format=mi_format_str_to_enum(r->v.cstr);
962 }
963 else if (strcmp(r->var,"attr")==0)
964 { /* Note: gdb 6.1.1 have only this: */
965 if (strcmp(r->v.cstr,"editable")==0)
966 res->attr=MI_ATTR_EDITABLE;
967 else /* noneditable */
968 res->attr=MI_ATTR_NONEDITABLE;
969 }
970 }
971 r=r->next;
972 }
973 return res;
974}
975
976mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression)
977{
978 mi_output *r, *res;
979 mi_gvar *gvar=NULL;
980
981 r=mi_get_response_blk(h);
982 res=mi_get_rrecord(r);
983 if (res && res->tclass==MI_CL_DONE)
984 gvar=mi_get_gvar(res,cur,expression);
985 mi_free_output(r);
986 return gvar;
987}
988
989mi_gvar_chg *mi_get_gvar_chg(mi_results *r)
990{
991 mi_gvar_chg *n;
992
993 if (r->type!=t_const)
994 return NULL;
995 n=mi_alloc_gvar_chg();
996 if (n)
997 {
998 while (r)
999 {
1000 if (r->type==t_const)
1001 {
1002 if (strcmp(r->var,"name")==0)
1003 {
1004 n->name=r->v.cstr;
1005 r->v.cstr=NULL;
1006 }
1007 else if (strcmp(r->var,"in_scope")==0)
1008 {
1009 n->in_scope=strcmp(r->v.cstr,"true")==0;
1010 }
1011 else if (strcmp(r->var,"new_type")==0)
1012 {
1013 n->new_type=r->v.cstr;
1014 r->v.cstr=NULL;
1015 }
1016 else if (strcmp(r->var,"new_num_children")==0)
1017 {
1018 n->new_num_children=atoi(r->v.cstr);
1019 }
1020 // type_changed="false" is the default
1021 }
1022 r=r->next;
1023 }
1024 }
1025 return n;
1026}
1027
1028int mi_res_changelist(mi_h *h, mi_gvar_chg **changed)
1029{
1030 mi_gvar_chg *last, *n;
1031 mi_results *res=mi_res_done_var(h,"changelist"), *r;
1032 int count=0;
1033
1034 *changed=NULL;
1035 if (!res)
1036 return 0;
1037 last=NULL;
1038 count=1;
1039 n=NULL;
1040 r=res->v.rs;
1041
1042 if (res->type==t_list)
1043 {// MI v2 a list of tuples
1044 while (r)
1045 {
1046 if (r->type==t_tuple)
1047 {
1048 n=mi_get_gvar_chg(r->v.rs);
1049 if (n)
1050 {
1051 if (last)
1052 last->next=n;
1053 else
1054 *changed=n;
1055 last=n;
1056 count++;
1057 }
1058 }
1059 r=r->next;
1060 }
1061 }
1062 else if (res->type==t_tuple)
1063 {// MI v1 a tuple with all together *8-P
1064 while (r)
1065 {
1066 if (r->type==t_const) /* Just in case. */
1067 {/* Get one var. */
1068 if (strcmp(r->var,"name")==0)
1069 {
1070 if (n)
1071 {/* Add to the list*/
1072 if (last)
1073 last->next=n;
1074 else
1075 *changed=n;
1076 last=n;
1077 count++;
1078 }
1079 n=mi_alloc_gvar_chg();
1080 if (!n)
1081 {
1082 mi_free_gvar_chg(*changed);
1083 return 0;
1084 }
1085 n->name=r->v.cstr;
1086 r->v.cstr=NULL;
1087 }
1088 else if ((NULL != n) && (strcmp(r->var,"in_scope")==0))
1089 {
1090 n->in_scope=strcmp(r->v.cstr,"true")==0;
1091 }
1092 else if ((NULL != n) && (strcmp(r->var,"new_type")==0))
1093 {
1094 n->new_type=r->v.cstr;
1095 r->v.cstr=NULL;
1096 }
1097 else if ((NULL != n) && (strcmp(r->var,"new_num_children")==0))
1098 {
1099 n->new_num_children=atoi(r->v.cstr);
1100 }
1101 // type_changed="false" is the default
1102 }
1103 r=r->next;
1104 }
1105 if (n)
1106 {/* Add to the list*/
1107 if (last)
1108 last->next=n;
1109 else
1110 *changed=n;
1111 last=n;
1112 count++;
1113 }
1114 }
1115 mi_free_results(res);
1116
1117 return count;
1118}
1119
1120int mi_get_children(mi_results *ch, mi_gvar *v)
1121{
1122 mi_gvar *cur=NULL, *aux;
1123 int i=0, count=v->numchild, l;
1124
1125 while (ch)
1126 {
1127 if (strcmp(ch->var,"child")==0 && ch->type==t_tuple && i<count)
1128 {
1129 mi_results *r=ch->v.rs;
1130 aux=mi_alloc_gvar();
1131 if (!aux)
1132 return 0;
1133 if (!v->child)
1134 v->child=aux;
1135 else if (NULL != cur)
1136 cur->next=aux;
1137 cur=aux;
1138 cur->parent=v;
1139 cur->depth=v->depth+1;
1140
1141 while (r)
1142 {
1143 if (r->type==t_const)
1144 {
1145 if (strcmp(r->var,"name")==0)
1146 {
1147 cur->name=r->v.cstr;
1148 r->v.cstr=NULL;
1149 }
1150 else if (strcmp(r->var,"exp")==0)
1151 {
1152 cur->exp=r->v.cstr;
1153 r->v.cstr=NULL;
1154 }
1155 else if (strcmp(r->var,"type")==0)
1156 {
1157 cur->type=r->v.cstr;
1158 r->v.cstr=NULL;
1159 l=strlen(cur->type);
1160 if (l && cur->type[l-1]=='*')
1161 cur->ispointer=1;
1162 }
1163 else if (strcmp(r->var,"value")==0)
1164 {
1165 cur->value=r->v.cstr;
1166 r->v.cstr=NULL;
1167 }
1168 else if (strcmp(r->var,"numchild")==0)
1169 {
1170 cur->numchild=atoi(r->v.cstr);
1171 }
1172 }
1173 r=r->next;
1174 }
1175 i++;
1176 }
1177 ch=ch->next;
1178 }
1179 v->vischild=i;
1180 v->opened=1;
1181 return i==v->numchild;
1182}
1183
1184int mi_res_children(mi_h *h, mi_gvar *v)
1185{
1186 mi_output *r, *res;
1187 int ok=0;
1188
1189 r=mi_get_response_blk(h);
1190 res=mi_get_rrecord(r);
1191 if (res && res->tclass==MI_CL_DONE)
1192 {
1193 mi_results *num=mi_get_var(res,"numchild");
1194 if (num && num->type==t_const)
1195 {
1196 v->numchild=atoi(num->v.cstr);
1197 if (v->child)
1198 {
1199 mi_free_gvar(v->child);
1200 v->child=NULL;
1201 }
1202 if (v->numchild)
1203 {
1204 mi_results *ch =mi_get_var(res,"children");
1205 if (ch && ch->type!=t_const) /* MI v1 tuple, MI v2 list */
1206 ok=mi_get_children(ch->v.rs,v);
1207 }
1208 else
1209 ok=1;
1210 }
1211 }
1212 mi_free_output(r);
1213 return ok;
1214}
1215
1216mi_bkpt *mi_get_bkpt(mi_results *p)
1217{
1218 mi_bkpt *res;
1219 char *end;
1220
1221 res=mi_alloc_bkpt();
1222 if (!res)
1223 return NULL;
1224 while (p)
1225 {
1226 if (p->type==t_const && p->var)
1227 {
1228 if (strcmp(p->var,"number")==0)
1229 res->number=atoi(p->v.cstr);
1230 else if (strcmp(p->var,"type")==0)
1231 {
1232 if (strcmp(p->v.cstr,"breakpoint")==0)
1233 res->type=t_breakpoint;
1234 else
1235 res->type=t_unknown;
1236 }
1237 else if (strcmp(p->var,"disp")==0)
1238 {
1239 if (strcmp(p->v.cstr,"keep")==0)
1240 res->disp=d_keep;
1241 else if (strcmp(p->v.cstr,"del")==0)
1242 res->disp=d_del;
1243 else
1244 res->disp=d_unknown;
1245 }
1246 else if (strcmp(p->var,"enabled")==0)
1247 res->enabled=p->v.cstr[0]=='y';
1248 else if (strcmp(p->var,"addr")==0)
1249 res->addr=(void *)strtoul(p->v.cstr,&end,0);
1250 else if (strcmp(p->var,"func")==0)
1251 {
1252 res->func=p->v.cstr;
1253 p->v.cstr=NULL;
1254 }
1255 else if (strcmp(p->var,"file")==0)
1256 {
1257 res->file=p->v.cstr;
1258 p->v.cstr=NULL;
1259 }
1260 else if (strcmp(p->var,"line")==0)
1261 res->line=atoi(p->v.cstr);
1262 else if (strcmp(p->var,"times")==0)
1263 res->times=atoi(p->v.cstr);
1264 else if (strcmp(p->var,"ignore")==0)
1265 res->ignore=atoi(p->v.cstr);
1266 else if (strcmp(p->var,"cond")==0)
1267 {
1268 res->cond=p->v.cstr;
1269 p->v.cstr=NULL;
1270 }
1271 }
1272 p=p->next;
1273 }
1274 return res;
1275}
1276
1277mi_bkpt *mi_res_bkpt(mi_h *h)
1278{
1279 mi_results *r=mi_res_done_var(h,"bkpt");
1280 mi_bkpt *b=NULL;
1281
1282 if (r && r->type==t_tuple)
1283 b=mi_get_bkpt(r->v.rs);
1284 mi_free_results(r);
1285 return b;
1286}
1287
1288mi_wp *mi_get_wp(mi_results *p, enum mi_wp_mode m)
1289{
1290 mi_wp *res=mi_alloc_wp();
1291
1292 if (res)
1293 {
1294 res->mode=m;
1295 while (p)
1296 {
1297 if (p->type==t_const && p->var)
1298 {
1299 if (strcmp(p->var,"number")==0)
1300 {
1301 res->number=atoi(p->v.cstr);
1302 res->enabled=1;
1303 }
1304 else if (strcmp(p->var,"exp")==0)
1305 {
1306 res->exp=p->v.cstr;
1307 p->v.cstr=NULL;
1308 }
1309 }
1310 p=p->next;
1311 }
1312 }
1313 return res;
1314}
1315
1316mi_wp *mi_parse_wp_res(mi_output *r)
1317{
1318 mi_results *p;
1319 enum mi_wp_mode m=wm_unknown;
1320
1321 /* The info is in a result wpt=... */
1322 p=r->c;
1323 while (p)
1324 {
1325 if (p->var)
1326 {
1327 if (strcmp(p->var,"wpt")==0)
1328 m=wm_write;
1329 else if (strcmp(p->var,"hw-rwpt")==0)
1330 m=wm_read;
1331 else if (strcmp(p->var,"hw-awpt")==0)
1332 m=wm_rw;
1333 if (m!=wm_unknown)
1334 break;
1335 }
1336 p=p->next;
1337 }
1338 if (!p || p->type!=t_tuple)
1339 return NULL;
1340 /* Scan the values inside it. */
1341 return mi_get_wp(p->v.rs,m);
1342}
1343
1344mi_wp *mi_res_wp(mi_h *h)
1345{
1346 mi_output *r, *res;
1347 mi_wp *ret=NULL;
1348
1349 r=mi_get_response_blk(h);
1350 res=mi_get_rrecord(r);
1351
1352 if (res)
1353 ret=mi_parse_wp_res(res);
1354
1355 mi_free_output(r);
1356 return ret;
1357}
1358
1359char *mi_res_value(mi_h *h)
1360{
1361 mi_results *r=mi_res_done_var(h,"value");
1362 char *s=NULL;
1363
1364 if (r && r->type==t_const)
1365 {
1366 s=r->v.cstr;
1367 r->v.rs=NULL;
1368 }
1369 mi_free_results(r);
1370 return s;
1371}
1372
1373mi_output *mi_get_stop_record(mi_output *r)
1374{
1375 while (r)
1376 {
1377 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
1378 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
1379 return r;
1380 r=r->next;
1381 }
1382 return r;
1383}
1384
1385static
1386char *reason_names[]=
1387{
1388 "breakpoint-hit",
1389 "watchpoint-trigger",
1390 "read-watchpoint-trigger",
1391 "access-watchpoint-trigger",
1392 "watchpoint-scope",
1393 "function-finished",
1394 "location-reached",
1395 "end-stepping-range",
1396 "exited-signalled",
1397 "exited",
1398 "exited-normally",
1399 "signal-received"
1400};
1401
1402static
1403enum mi_stop_reason reason_values[]=
1404{
1405 sr_bkpt_hit,
1406 sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
1407 sr_function_finished, sr_location_reached, sr_end_stepping_range,
1408 sr_exited_signalled, sr_exited, sr_exited_normally,
1409 sr_signal_received
1410};
1411
1412static
1413char *reason_expl[]=
1414{
1415 "Hit a breakpoint",
1416 "Write watchpoint",
1417 "Read watchpoint",
1418 "Access watchpoint",
1419 "Watchpoint out of scope",
1420 "Function finished",
1421 "Location reached",
1422 "End of stepping",
1423 "Exited signalled",
1424 "Exited with error",
1425 "Exited normally",
1426 "Signal received"
1427};
1428
1429enum mi_stop_reason mi_reason_str_to_enum(const char *s)
1430{
1431 int i;
1432
1433 for (i=0; i<sizeof(reason_names)/sizeof(char *); i++)
1434 if (strcmp(reason_names[i],s)==0)
1435 return reason_values[i];
1436 return sr_unknown;
1437}
1438
1439const char *mi_reason_enum_to_str(enum mi_stop_reason r)
1440{
1441 int i;
1442
1443 if (r==sr_unknown)
1444 return "Unknown (temp bkp?)";
1445 for (i=0; i<sizeof(reason_values)/sizeof(char *); i++)
1446 if (reason_values[i]==r)
1447 return reason_expl[i];
1448 return NULL;
1449}
1450
1451mi_stop *mi_get_stopped(mi_results *r)
1452{
1453 mi_stop *res=mi_alloc_stop();
1454
1455 if (res)
1456 {
1457 while (r)
1458 {
1459 if (r->type==t_const)
1460 {
1461 if (strcmp(r->var,"reason")==0)
1462 res->reason=mi_reason_str_to_enum(r->v.cstr);
1463 else if (!res->have_thread_id && strcmp(r->var,"thread-id")==0)
1464 {
1465 res->have_thread_id=1;
1466 res->thread_id=atoi(r->v.cstr);
1467 }
1468 else if (!res->have_bkptno && strcmp(r->var,"bkptno")==0)
1469 {
1470 res->have_bkptno=1;
1471 res->bkptno=atoi(r->v.cstr);
1472 }
1473 else if (!res->have_bkptno && strcmp(r->var,"wpnum")==0)
1474 {
1475 res->have_wpno=1;
1476 res->wpno=atoi(r->v.cstr);
1477 }
1478 else if (strcmp(r->var,"gdb-result-var")==0)
1479 {
1480 res->gdb_result_var=r->v.cstr;
1481 r->v.cstr=NULL;
1482 }
1483 else if (strcmp(r->var,"return-value")==0)
1484 {
1485 res->return_value=r->v.cstr;
1486 r->v.cstr=NULL;
1487 }
1488 else if (strcmp(r->var,"signal-name")==0)
1489 {
1490 res->signal_name=r->v.cstr;
1491 r->v.cstr=NULL;
1492 }
1493 else if (strcmp(r->var,"signal-meaning")==0)
1494 {
1495 res->signal_meaning=r->v.cstr;
1496 r->v.cstr=NULL;
1497 }
1498 else if (!res->have_exit_code && strcmp(r->var,"exit-code")==0)
1499 {
1500 res->have_exit_code=1;
1501 res->exit_code=atoi(r->v.cstr);
1502 }
1503 }
1504 else // tuple or list
1505 {
1506 if (strcmp(r->var,"frame")==0)
1507 res->frame=mi_parse_frame(r->v.rs);
1508 else if (!res->wp && strcmp(r->var,"wpt")==0)
1509 res->wp=mi_get_wp(r->v.rs,wm_write);
1510 else if (!res->wp && strcmp(r->var,"hw-rwpt")==0)
1511 res->wp=mi_get_wp(r->v.rs,wm_read);
1512 else if (!res->wp && strcmp(r->var,"hw-awpt")==0)
1513 res->wp=mi_get_wp(r->v.rs,wm_rw);
1514 else if (!(res->wp_old || res->wp_val) && strcmp(r->var,"value")==0)
1515 {
1516 mi_results *p=r->v.rs;
1517 while (p)
1518 {
1519 if (strcmp(p->var,"value")==0 || strcmp(p->var,"new")==0)
1520 {
1521 res->wp_val=p->v.cstr;
1522 p->v.cstr=NULL;
1523 }
1524 else if (strcmp(p->var,"old")==0)
1525 {
1526 res->wp_old=p->v.cstr;
1527 p->v.cstr=NULL;
1528 }
1529 p=p->next;
1530 }
1531 }
1532 }
1533 r=r->next;
1534 }
1535 }
1536 return res;
1537}
1538
1539mi_stop *mi_res_stop(mi_h *h)
1540{
1541 mi_output *o=mi_retire_response(h);
1542 mi_stop *stop=NULL;
1543
1544 if (o)
1545 {
1546 mi_output *sr=mi_get_stop_record(o);
1547 if (sr)
1548 stop=mi_get_stopped(sr->c);
1549 }
1550 mi_free_output(o);
1551
1552 return stop;
1553}
1554
1555int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
1556 unsigned long *addr)
1557{
1558 char *end;
1559 mi_results *res=mi_res_done_var(h,"memory"), *r;
1560 int ok=0;
1561
1562 *na=0;
1563 r=res;
1564 if (r && r->type==t_list && ws==1)
1565 {
1566 r=r->v.rs;
1567 if (r->type!=t_tuple)
1568 {
1569 mi_free_results(res);
1570 return 0;
1571 }
1572 r=r->v.rs;
1573 while (r)
1574 {
1575 if (r->type==t_list && strcmp(r->var,"data")==0)
1576 {
1577 mi_results *data=r->v.rs;
1578 ok++;
1579 if (data && data->type==t_const &&
1580 strcmp(data->v.cstr,"N/A")==0)
1581 *na=1;
1582 else
1583 while (data)
1584 {
1585 if (data->type==t_const)
1586 *(dest++)=strtol(data->v.cstr,&end,0);
1587 data=data->next;
1588 }
1589 }
1590 else if (r->type==t_const && strcmp(r->var,"addr")==0)
1591 {
1592 ok++;
1593 if (addr)
1594 *addr=strtoul(r->v.cstr,&end,0);
1595 }
1596 r=r->next;
1597 }
1598
1599 }
1600 mi_free_results(res);
1601 return ok==2;
1602}
1603
1604mi_asm_insn *mi_parse_insn(mi_results *c)
1605{
1606 mi_asm_insn *res=NULL, *cur=NULL;
1607 mi_results *sub;
1608 char *end;
1609
1610 while (c)
1611 {
1612 if (c->type==t_tuple)
1613 {
1614 if (!res)
1615 res=cur=mi_alloc_asm_insn();
1616 else
1617 {
1618 cur->next=mi_alloc_asm_insn();
1619 cur=cur->next;
1620 }
1621 if (!cur)
1622 {
1623 mi_free_asm_insn(res);
1624 return NULL;
1625 }
1626 sub=c->v.rs;
1627 while (sub)
1628 {
1629 if (sub->type==t_const)
1630 {
1631 if (strcmp(sub->var,"address")==0)
1632 cur->addr=(void *)strtoul(sub->v.cstr,&end,0);
1633 else if (strcmp(sub->var,"func-name")==0)
1634 {
1635 cur->func=sub->v.cstr;
1636 sub->v.cstr=NULL;
1637 }
1638 else if (strcmp(sub->var,"offset")==0)
1639 cur->offset=atoi(sub->v.cstr);
1640 else if (strcmp(sub->var,"inst")==0)
1641 {
1642 cur->inst=sub->v.cstr;
1643 sub->v.cstr=NULL;
1644 }
1645 }
1646 sub=sub->next;
1647 }
1648 }
1649 c=c->next;
1650 }
1651 return res;
1652}
1653
1654mi_asm_insns *mi_parse_insns(mi_results *c)
1655{
1656 mi_asm_insns *res=NULL, *cur=NULL;
1657 mi_results *sub;
1658
1659 while (c)
1660 {
1661 if (c->var)
1662 {
1663 if (strcmp(c->var,"src_and_asm_line")==0 && c->type==t_tuple)
1664 {
1665 if (!res)
1666 res=cur=mi_alloc_asm_insns();
1667 else
1668 {
1669 cur->next=mi_alloc_asm_insns();
1670 cur=cur->next;
1671 }
1672 if (!cur)
1673 {
1674 mi_free_asm_insns(res);
1675 return NULL;
1676 }
1677 sub=c->v.rs;
1678 while (sub)
1679 {
1680 if (sub->var)
1681 {
1682 if (sub->type==t_const)
1683 {
1684 if (strcmp(sub->var,"line")==0)
1685 cur->line=atoi(sub->v.cstr);
1686 else if (strcmp(sub->var,"file")==0)
1687 {
1688 cur->file=sub->v.cstr;
1689 sub->v.cstr=NULL;
1690 }
1691 }
1692 else if (sub->type==t_list)
1693 {
1694 if (strcmp(sub->var,"line_asm_insn")==0)
1695 cur->ins=mi_parse_insn(sub->v.rs);
1696 }
1697 }
1698 sub=sub->next;
1699 }
1700 }
1701 }
1702 else
1703 {/* No source line, just instructions */
1704 res=mi_alloc_asm_insns();
1705 res->ins=mi_parse_insn(c);
1706 break;
1707 }
1708 c=c->next;
1709 }
1710 return res;
1711}
1712
1713
1714mi_asm_insns *mi_get_asm_insns(mi_h *h)
1715{
1716 mi_results *r=mi_res_done_var(h,"asm_insns");
1717 mi_asm_insns *f=NULL;
1718
1719 if (r && r->type==t_list)
1720 f=mi_parse_insns(r->v.rs);
1721 mi_free_results(r);
1722 return f;
1723}
1724
1725mi_chg_reg *mi_parse_list_regs(mi_results *r, int *how_many)
1726{
1727 mi_results *c=r;
1728 int cregs=0;
1729 mi_chg_reg *first=NULL, *cur=NULL;
1730
1731 /* Create the list. */
1732 while (c)
1733 {
1734 if (c->type==t_const && !c->var)
1735 {
1736 if (first)
1737 cur=cur->next=mi_alloc_chg_reg();
1738 else
1739 first=cur=mi_alloc_chg_reg();
1740
1741 if (NULL != cur) {
1742 cur->name=c->v.cstr;
1743 cur->reg=cregs++;
1744 c->v.cstr=NULL;
1745 }
1746 }
1747 c=c->next;
1748 }
1749 if (how_many)
1750 *how_many=cregs;
1751
1752 return first;
1753}
1754
1755mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many)
1756{
1757 mi_results *r=mi_res_done_var(h,"register-names");
1758 mi_chg_reg *l=NULL;
1759
1760 if (r && r->type==t_list)
1761 l=mi_parse_list_regs(r->v.rs,how_many);
1762 mi_free_results(r);
1763 return l;
1764}
1765
1766mi_chg_reg *mi_parse_list_changed_regs(mi_results *r)
1767{
1768 mi_results *c=r;
1769 mi_chg_reg *first=NULL, *cur=NULL;
1770
1771 /* Create the list. */
1772 while (c)
1773 {
1774 if (c->type==t_const && !c->var)
1775 {
1776 if (first)
1777 cur=cur->next=mi_alloc_chg_reg();
1778 else
1779 first=cur=mi_alloc_chg_reg();
1780 cur->reg=atoi(c->v.cstr);
1781 }
1782 c=c->next;
1783 }
1784
1785 return first;
1786}
1787
1788mi_chg_reg *mi_get_list_changed_regs(mi_h *h)
1789{
1790 mi_results *r=mi_res_done_var(h,"changed-registers");
1791 mi_chg_reg *changed=NULL;
1792
1793 if (r && r->type==t_list)
1794 changed=mi_parse_list_changed_regs(r->v.rs);
1795 mi_free_results(r);
1796 return changed;
1797}
1798
1799int mi_parse_reg_values(mi_results *r, mi_chg_reg *l)
1800{
1801 mi_results *c;
1802
1803 while (r && l)
1804 {
1805 if (r->type==t_tuple && !r->var)
1806 {
1807 c=r->v.rs;
1808 while (c)
1809 {
1810 if (c->type==t_const && c->var)
1811 {
1812 if (strcmp(c->var,"number")==0)
1813 {
1814 if (atoi(c->v.cstr)!=l->reg)
1815 {
1816 mi_error=MI_PARSER;
1817 return 0;
1818 }
1819 }
1820 else if (strcmp(c->var,"value")==0)
1821 {
1822 l->val=c->v.cstr;
1823 c->v.cstr=NULL;
1824 }
1825 }
1826 c=c->next;
1827 }
1828 }
1829 r=r->next;
1830 l=l->next;
1831 }
1832
1833 return !l && !r;
1834}
1835
1836int mi_get_reg_values(mi_h *h, mi_chg_reg *l)
1837{
1838 mi_results *r=mi_res_done_var(h,"register-values");
1839 int ok=0;
1840
1841 if (r && r->type==t_list)
1842 ok=mi_parse_reg_values(r->v.rs,l);
1843 mi_free_results(r);
1844 return ok;
1845}
1846
1847int mi_parse_list_regs_l(mi_results *r, mi_chg_reg *l)
1848{
1849 while (r && l)
1850 {
1851 if (r->type==t_const && !r->var)
1852 {
1853 free(l->name);
1854 l->name=r->v.cstr;
1855 r->v.cstr=NULL;
1856 l=l->next;
1857 }
1858 r=r->next;
1859 }
1860
1861 return !l && !r;
1862}
1863
1864int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l)
1865{
1866 mi_results *r=mi_res_done_var(h,"register-names");
1867 int ok=0;
1868
1869 if (r && r->type==t_list)
1870 ok=mi_parse_list_regs_l(r->v.rs,l);
1871 mi_free_results(r);
1872 return ok;
1873}
1874
1875mi_chg_reg *mi_parse_reg_values_l(mi_results *r, int *how_many)
1876{
1877 mi_results *c;
1878 mi_chg_reg *first=NULL, *cur=NULL;
1879 *how_many=0;
1880
1881 while (r)
1882 {
1883 if (r->type==t_tuple && !r->var)
1884 {
1885 c=r->v.rs;
1886 if (first)
1887 cur=cur->next=mi_alloc_chg_reg();
1888 else
1889 first=cur=mi_alloc_chg_reg();
1890 while (c)
1891 {
1892 if (c->type==t_const && c->var)
1893 {
1894 if (strcmp(c->var,"number")==0)
1895 {
1896 if (NULL != cur)
1897 cur->reg=atoi(c->v.cstr);
1898 (*how_many)++;
1899 }
1900 else if (strcmp(c->var,"value")==0)
1901 {
1902 if (NULL != cur)
1903 cur->val=c->v.cstr;
1904 c->v.cstr=NULL;
1905 }
1906 }
1907 c=c->next;
1908 }
1909 }
1910 r=r->next;
1911 }
1912
1913 return first;
1914}
1915
1916mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many)
1917{
1918 mi_results *r=mi_res_done_var(h,"register-values");
1919 mi_chg_reg *rgs=NULL;
1920
1921 if (r && r->type==t_list)
1922 rgs=mi_parse_reg_values_l(r->v.rs,how_many);
1923 mi_free_results(r);
1924 return rgs;
1925}
1926
1927
diff --git a/pathologist/src/mi/gdbmi_prg_control.c b/pathologist/src/mi/gdbmi_prg_control.c
new file mode 100644
index 0000000..80ac7af
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_prg_control.c
@@ -0,0 +1,598 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Program control.
7 Comments:
8 GDB/MI commands for the "Program Control" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12
13-exec-abort N.A. (*) (kill, but with non-interactive options)
14-exec-arguments Yes
15-exec-continue Yes ASYNC
16-exec-finish Yes ASYNC
17-exec-interrupt Yes ASYNC
18-exec-next Yes ASYNC
19-exec-next-instruction Yes ASYNC
20-exec-return Yes
21-exec-run Yes ASYNC
22-exec-show-arguments N.A. (show args) see gmi_stack_info_frame
23-exec-step Yes ASYNC
24-exec-step-instruction Yes ASYNC
25-exec-until Yes ASYNC
26-file-exec-and-symbols Yes
27-file-exec-file No
28-file-list-exec-sections N.A. (info file)
29-file-list-exec-source-files N.A.
30-file-list-shared-libraries N.A.
31-file-list-symbol-files N.A.
32-file-symbol-file Yes
33@</pre>
34
35(*) gmi_exec_kill implements it, but you should ensure that
36gmi_gdb_set("confirm","off") was called. @<p>
37
38GDB Bug workaround for -file-exec-and-symbols and -file-symbol-file: This
39is complex, but a real bug. When you set a breakpoint you never know the
40name of the file as it appears in the debug info. So you can be specifying
41an absolute file name or a relative file name. The reference point could be
42different than the one used in the debug info. To solve all the combinations
43gdb does a search trying various combinations. GDB isn't very smart so you
44must at least specify the working directory and the directory where the
45binary is located to get a good chance (+ user options to solve the rest).
46Once you did it gdb can find the file by doing transformations to the
47"canonical" filename. This search works OK for already loaded symtabs
48(symbol tables), but it have a bug when the search is done for psymtabs
49(partial symtabs). The bug is in the use of source_full_path_of (source.c).
50This function calls openp indicating try_cwd_first. It makes the search file
51if the psymtab file name have at least one dirseparator. It means that
52psymtabs for files compiled with relative paths will fail. The search for
53symtabs uses symtab_to_filename, it calls open_source_file which finally
54calls openp without try_cwd_first.@*
55To workaround this bug we must ensure gdb loads *all* the symtabs to memory.
56And here comes another problem -file-exec-and-symbols doesn't support it
57according to docs. In real life that's a wrapper for "file", but as nobody
58can say it won't change we must use the CLI command.
59
60***************************************************************************/
61
62#include <signal.h>
63#include "gdbmi.h"
64
65/* Low level versions. */
66
67void mi_file_exec_and_symbols(mi_h *h, const char *file)
68{
69 if (mi_get_workaround(MI_PSYM_SEARCH))
70 mi_send(h,"file %s -readnow\n",file);
71 else
72 mi_send(h,"-file-exec-and-symbols %s\n",file);
73}
74
75void mi_set_unwind_on_signal_on(mi_h *h)
76{
77 mi_send(h, "set unwindonsignal on\n");
78}
79
80void mi_exec_arguments(mi_h *h, const char *args)
81{
82 mi_send(h,"-exec-arguments %s\n",args);
83}
84
85void mi_exec_run(mi_h *h)
86{
87 mi_send(h,"-exec-run\n");
88}
89
90void mi_exec_continue(mi_h *h)
91{
92 mi_send(h,"-exec-continue\n");
93}
94
95void mi_exec_continue_reverse(mi_h *h)
96{
97 mi_send(h, "-exec-continue --reverse\n");
98}
99
100void mi_target_terminal(mi_h *h, const char *tty_name)
101{
102 mi_send(h,"tty %s\n",tty_name);
103}
104
105void mi_file_symbol_file(mi_h *h, const char *file)
106{
107 if (mi_get_workaround(MI_PSYM_SEARCH))
108 mi_send(h,"symbol-file %s -readnow\n",file);
109 else
110 mi_send(h,"-file-symbol-file %s\n",file);
111}
112
113void mi_exec_finish(mi_h *h)
114{
115 mi_send(h,"-exec-finish\n");
116}
117
118void mi_exec_finish_reverse(mi_h * h)
119{
120 mi_send(h, "-exec-finish --reverse\n");
121}
122void mi_exec_interrupt(mi_h *h)
123{
124 mi_send(h,"-exec-interrupt\n");
125}
126
127void mi_exec_record_process(mi_h *h)
128{
129mi_send(h, "-interpreter-exec mi record\n");
130}
131
132void mi_exec_record_stop(mi_h *h)
133{
134mi_send(h, "-interpreter-exec mi record stop\n");
135}
136
137void mi_exec_next(mi_h *h, int count)
138{
139 if (count>1)
140 mi_send(h,"-exec-next %d\n",count);
141 else
142 mi_send(h,"-exec-next\n");
143}
144
145void mi_exec_next_instruction(mi_h *h)
146{
147 mi_send(h,"-exec-next-instruction\n");
148}
149
150void mi_exec_step(mi_h *h, int count)
151{
152 if (count>1)
153 mi_send(h,"-exec-step %d\n",count);
154 else
155 mi_send(h,"-exec-step\n");
156}
157
158
159void mi_exec_step_back(mi_h *h, int count)
160{
161 if (count>1)
162 mi_send(h, "-exec-step %d --reverse\n", count);
163 else
164 mi_send(h, "-exec-step --reverse\n");
165}
166
167
168void mi_exec_next_reverse(mi_h *h, int count)
169{
170 if (count>1)
171 mi_send(h, "-exec-next %d --reverse\n", count);
172 else
173 mi_send(h, "-exec-next --reverse\n");
174}
175
176
177void mi_exec_step_instruction(mi_h *h)
178{
179 mi_send(h,"-exec-step-instruction\n");
180}
181
182void mi_exec_until(mi_h *h, const char *file, int line)
183{
184 if (!file)
185 mi_send(h,"-exec-until\n");
186 else
187 mi_send(h,"-exec-until %s:%d\n",file,line);
188}
189
190void mi_exec_until_addr(mi_h *h, void *addr)
191{
192 mi_send(h,"-exec-until *%p\n",addr);
193}
194
195void mi_exec_return(mi_h *h)
196{
197 mi_send(h,"-exec-return\n");
198}
199
200void mi_exec_kill(mi_h *h)
201{
202 mi_send(h,"kill\n");
203}
204
205/* High level versions. */
206
207/**[txh]********************************************************************
208
209 Description:
210 Specify the executable and arguments for local debug.
211
212 Command: -file-exec-and-symbols + -exec-arguments
213 Return: !=0 OK
214
215***************************************************************************/
216
217int gmi_set_exec(mi_h *h, const char *file, const char *args)
218{
219 mi_file_exec_and_symbols(h,file);
220 if (!mi_res_simple_done(h))
221 return 0;
222 if (!args)
223 return 1;
224 mi_exec_arguments(h,args);
225 return mi_res_simple_done(h);
226}
227
228int gmi_set_unwind_on_signal_on(mi_h * h)
229{
230 mi_set_unwind_on_signal_on(h);
231 return mi_res_simple_running(h);
232}
233
234/**[txh]********************************************************************
235
236 Description:
237 Start running the executable. Remote sessions starts running.
238
239 Command: -exec-run
240 Return: !=0 OK
241
242***************************************************************************/
243
244int gmi_exec_run(mi_h *h)
245{
246 mi_exec_run(h);
247 return mi_res_simple_running(h);
248}
249
250/**[txh]********************************************************************
251
252 Description:
253 Continue the execution after a "stop".
254
255 Command: -exec-continue
256 Return: !=0 OK
257
258***************************************************************************/
259
260int gmi_exec_continue(mi_h *h)
261{
262 mi_exec_continue(h);
263 return mi_res_simple_running(h);
264}
265
266/**[txh]********************************************************************
267
268 Description:
269 Continue the execution in reverse order after a "stop".
270
271 Command: -exec-continue --reverse
272 Return: !=0 OK
273
274***************************************************************************/
275int gmi_exec_continue_reverse(mi_h *h)
276{
277 mi_exec_continue_reverse(h);
278 return mi_res_simple_running(h);
279}
280
281/**[txh]********************************************************************
282
283 Description:
284 Indicate which terminal will use the target program. For local sessions.
285
286 Command: tty
287 Return: !=0 OK
288 Example:
289
290***************************************************************************/
291
292int gmi_target_terminal(mi_h *h, const char *tty_name)
293{
294 mi_target_terminal(h,tty_name);
295 return mi_res_simple_done(h);
296}
297
298/**[txh]********************************************************************
299
300 Description:
301 Specify what's the local copy that have debug info. For remote sessions.
302
303 Command: -file-symbol-file
304 Return: !=0 OK
305
306***************************************************************************/
307
308int gmi_file_symbol_file(mi_h *h, const char *file)
309{
310 mi_file_symbol_file(h,file);
311 return mi_res_simple_done(h);
312}
313
314/**[txh]********************************************************************
315
316 Description:
317 Continue until function return, the return value is included in the async
318response.
319
320 Command: -exec-finish
321 Return: !=0 OK.
322
323***************************************************************************/
324
325int gmi_exec_finish(mi_h *h)
326{
327 mi_exec_finish(h);
328 return mi_res_simple_running(h);
329}
330
331/**[txh]********************************************************************
332
333 Description:
334 Continue backwardly until function return, the return value is included in
335 the async response.
336
337 Command: -exec-finish --reverse
338 Return: !=0 OK.
339
340***************************************************************************/
341int gmi_exec_finish_reverse(mi_h *h)
342{
343 mi_exec_finish_reverse(h);
344 return mi_res_simple_running(h);
345}
346
347/**[txh]********************************************************************
348
349 Description:
350 Stop the program using SIGINT. The corresponding command should be
351-exec-interrupt but not even gdb 6.1.1 can do it because the "async" mode
352isn't really working.
353
354 Command: -exec-interrupt [replacement]
355 Return: Always 1
356 Example:
357
358***************************************************************************/
359
360int gmi_exec_interrupt(mi_h *h)
361{
362 // **** IMPORTANT!!! **** Not even gdb 6.1.1 can do it because the "async"
363 // mode isn't really working.
364 //mi_exec_interrupt(h);
365 //return mi_res_simple_running(h);
366
367 kill(h->pid,SIGINT);
368 return 1; // How can I know?
369}
370
371/**[txh]********************************************************************
372
373 Description:
374 Next line of code.
375
376 Command: -exec-next
377 Return: !=0 OK
378
379***************************************************************************/
380
381int gmi_exec_next(mi_h *h)
382{
383 mi_exec_next(h,1);
384 return mi_res_simple_running(h);
385}
386
387/**[txh]********************************************************************
388
389 Description:
390 Start recording a process
391
392 Command: -interpreter-exec mi record
393 Return: !=0 OK
394
395***************************************************************************/
396int gmi_exec_record_process(mi_h *h)
397{
398 mi_exec_record_process(h);
399 return 1;
400}
401
402/**[txh]********************************************************************
403
404 Description:
405 Start recording a process
406
407 Command: -interpreter-exec mi record stop
408 Return: !=0 OK
409
410***************************************************************************/
411int gmi_exec_record_stop(mi_h *h)
412{
413 mi_exec_record_stop(h);
414 return 1;
415}
416
417/**[txh]********************************************************************
418
419 Description:
420 Skip count lines of code.
421
422 Command: -exec-next count
423 Return: !=0 OK
424
425***************************************************************************/
426
427int gmi_exec_next_cnt(mi_h *h, int count)
428{
429 mi_exec_next(h,count);
430 return mi_res_simple_running(h);
431}
432
433/**[txh]********************************************************************
434
435 Description:
436 Next line of assembler code.
437
438 Command: -exec-next-instruction
439 Return: !=0 OK
440
441***************************************************************************/
442
443int gmi_exec_next_instruction(mi_h *h)
444{
445 mi_exec_next_instruction(h);
446 return mi_res_simple_running(h);
447}
448
449/**[txh]********************************************************************
450
451 Description:
452 Next line of code. Get inside functions.
453
454 Command: -exec-step
455 Return: !=0 OK
456
457***************************************************************************/
458
459int gmi_exec_step(mi_h *h)
460{
461 mi_exec_step(h,1);
462 return mi_res_simple_running(h);
463}
464
465
466
467/**[txh]********************************************************************
468
469 Description:
470 Previous line of code. Get inside functions.
471
472 Command: -exec-step --reverse
473 Return: !=0 OK
474
475***************************************************************************/
476int gmi_exec_step_back(mi_h *h)
477{
478 mi_exec_step_back(h,1);
479 return mi_res_simple_running(h);
480}
481
482
483/**[txh]********************************************************************
484
485 Description:
486 Previous line of code (do not step into).
487
488 Command: -exec-next --reverse
489 Return: !=0 OK
490
491***************************************************************************/
492int gmi_exec_next_reverse(mi_h *h)
493{
494 mi_exec_next_reverse(h,1);
495 return mi_res_simple_running(h);
496}
497
498
499/**[txh]********************************************************************
500
501 Description:
502 Next count lines of code. Get inside functions.
503
504 Command: -exec-step count
505 Return: !=0 OK
506
507***************************************************************************/
508
509int gmi_exec_step_cnt(mi_h *h, int count)
510{
511 mi_exec_step(h,count);
512 return mi_res_simple_running(h);
513}
514
515/**[txh]********************************************************************
516
517 Description:
518 Next line of assembler code. Get inside calls.
519
520 Command: -exec-step-instruction
521 Return: !=0 OK
522
523***************************************************************************/
524
525int gmi_exec_step_instruction(mi_h *h)
526{
527 mi_exec_step_instruction(h);
528 return mi_res_simple_running(h);
529}
530
531/**[txh]********************************************************************
532
533 Description:
534 Execute until location is reached. If file is NULL then is until next
535line.
536
537 Command: -exec-until
538 Return: !=0 OK
539
540***************************************************************************/
541
542int gmi_exec_until(mi_h *h, const char *file, int line)
543{
544 mi_exec_until(h,file,line);
545 return mi_res_simple_running(h);
546}
547
548/**[txh]********************************************************************
549
550 Description:
551 Execute until location is reached.
552
553 Command: -exec-until (using *address)
554 Return: !=0 OK
555
556***************************************************************************/
557
558int gmi_exec_until_addr(mi_h *h, void *addr)
559{
560 mi_exec_until_addr(h,addr);
561 return mi_res_simple_running(h);
562}
563
564/**[txh]********************************************************************
565
566 Description:
567 Return to previous frame inmediatly.
568
569 Command: -exec-return
570 Return: A pointer to a new mi_frames structure indicating the current
571location. NULL on error.
572
573***************************************************************************/
574
575mi_frames *gmi_exec_return(mi_h *h)
576{
577 mi_exec_return(h);
578 return mi_res_frame(h);
579}
580
581/**[txh]********************************************************************
582
583 Description:
584 Just kill the program. That's what -exec-abort should do, but it isn't
585implemented by gdb. This implementation only works if the interactive mode
586is disabled (gmi_gdb_set("confirm","off")).
587
588 Command: -exec-abort [using kill]
589 Return: !=0 OK
590
591***************************************************************************/
592
593int gmi_exec_kill(mi_h *h)
594{
595 mi_exec_kill(h);
596 return mi_res_simple_done(h);
597}
598
diff --git a/pathologist/src/mi/gdbmi_stack_man.c b/pathologist/src/mi/gdbmi_stack_man.c
new file mode 100644
index 0000000..977ea5e
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_stack_man.c
@@ -0,0 +1,222 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Stack manipulation.
7 Comments:
8 GDB/MI commands for the "Stack Manipulation" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12
13-stack-info-frame Yes, implemented as "frame"
14-stack-info-depth Yes
15-stack-list-arguments Yes
16-stack-list-frames Yes
17-stack-list-locals Yes
18-stack-select-frame Yes
19@</pre>
20
21***************************************************************************/
22
23#include "gdbmi.h"
24
25/* Low level versions. */
26
27void mi_stack_list_frames(mi_h *h, int from, int to)
28{
29 if (from<0)
30 mi_send(h,"-stack-list-frames\n");
31 else
32 mi_send(h,"-stack-list-frames %d %d\n",from,to);
33}
34
35void mi_stack_list_arguments(mi_h *h, int show, int from, int to)
36{
37 if (from<0)
38 mi_send(h,"-stack-list-arguments %d\n",show);
39 else
40 mi_send(h,"-stack-list-arguments %d %d %d\n",show,from,to);
41}
42
43void mi_stack_info_frame(mi_h *h)
44{
45 mi_send(h,"frame\n");
46}
47
48void mi_stack_info_depth(mi_h *h, int depth)
49{
50 if (depth<0)
51 mi_send(h,"-stack-info-depth\n");
52 else
53 mi_send(h,"-stack-info-depth %d\n",depth);
54}
55
56void mi_stack_select_frame(mi_h *h, int framenum)
57{
58 mi_send(h,"-stack-select-frame %d\n",framenum);
59}
60
61void mi_stack_list_locals(mi_h *h, int show)
62{
63 mi_send(h,"-stack-list-locals %d\n",show);
64}
65
66/* High level versions. */
67
68/**[txh]********************************************************************
69
70 Description:
71 List of frames. Arguments aren't filled.
72
73 Command: -stack-list-frames
74 Return: A new list of mi_frames or NULL on error.
75
76***************************************************************************/
77
78mi_frames *gmi_stack_list_frames(mi_h *h)
79{
80 mi_stack_list_frames(h,-1,-1);
81 return mi_res_frames_array(h,"stack");
82}
83
84/**[txh]********************************************************************
85
86 Description:
87 List of frames. Arguments aren't filled. Only the frames in the from
88 - to range are returned.
89
90 Command: -stack-list-frames
91 Return: A new list of mi_frames or NULL on error.
92
93***************************************************************************/
94
95mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to)
96{
97 mi_stack_list_frames(h,from,to);
98 return mi_res_frames_array(h,"stack");
99}
100
101/**[txh]********************************************************************
102
103 Description:
104 List arguments. Only level and args filled.
105
106 Command: -stack-list-arguments
107 Return: A new list of mi_frames or NULL on error.
108
109***************************************************************************/
110
111mi_frames *gmi_stack_list_arguments(mi_h *h, int show)
112{
113 mi_stack_list_arguments(h,show,-1,-1);
114 return mi_res_frames_array(h,"stack-args");
115}
116
117/**[txh]********************************************************************
118
119 Description:
120 List arguments. Only level and args filled. Only for the
121frames in the from - to range.
122
123 Command: -stack-list-arguments
124 Return: A new list of mi_frames or NULL on error.
125
126***************************************************************************/
127
128mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to)
129{
130 mi_stack_list_arguments(h,show,from,to);
131 return mi_res_frames_array(h,"stack-args");
132}
133
134/**[txh]********************************************************************
135
136 Description:
137 Information about the current frame, including args.
138
139 Command: -stack-info-frame [using frame]
140 Return: A new mi_frames or NULL on error.
141
142***************************************************************************/
143
144mi_frames *gmi_stack_info_frame(mi_h *h)
145{
146 mi_stack_info_frame(h);
147 return mi_res_frame(h);
148}
149
150/**[txh]********************************************************************
151
152 Description:
153 Stack info depth.
154
155 Command: -stack-info-depth
156 Return: The depth or -1 on error.
157
158***************************************************************************/
159
160int gmi_stack_info_depth(mi_h *h, int max_depth)
161{
162 mi_results *r;
163 int ret=-1;
164
165 mi_stack_info_depth(h,max_depth);
166 r=mi_res_done_var(h,"depth");
167 if (r && r->type==t_const)
168 {
169 ret=atoi(r->v.cstr);
170 mi_free_results(r);
171 }
172 return ret;
173}
174
175/**[txh]********************************************************************
176
177 Description:
178 Set stack info depth.
179
180 Command: -stack-info-depth [no args]
181 Return: The depth or -1 on error.
182 Example:
183
184***************************************************************************/
185
186int gmi_stack_info_depth_get(mi_h *h)
187{
188 return gmi_stack_info_depth(h,-1);
189}
190
191/**[txh]********************************************************************
192
193 Description:
194 Change current frame.
195
196 Command: -stack-select-frame
197 Return: !=0 OK
198
199***************************************************************************/
200
201int gmi_stack_select_frame(mi_h *h, int framenum)
202{
203 mi_stack_select_frame(h,framenum);
204 return mi_res_simple_done(h);
205}
206
207/**[txh]********************************************************************
208
209 Description:
210 List of local vars.
211
212 Command: -stack-list-locals
213 Return: A new mi_results tree containing the variables or NULL on error.
214
215***************************************************************************/
216
217mi_results *gmi_stack_list_locals(mi_h *h, int show)
218{
219 mi_stack_list_locals(h,show);
220 return mi_res_done_var(h,"locals");
221}
222
diff --git a/pathologist/src/mi/gdbmi_symbol_query.c b/pathologist/src/mi/gdbmi_symbol_query.c
new file mode 100644
index 0000000..8910517
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_symbol_query.c
@@ -0,0 +1,32 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Symbol query.
7 Comments:
8 GDB/MI commands for the "Symbol Query" section.@p
9
10@<pre>
11gdb command: Implemented?
12-symbol-info-address N.A. (info address, human readable)
13-symbol-info-file N.A.
14-symbol-info-function N.A.
15-symbol-info-line N.A. (info line, human readable)
16-symbol-info-symbol N.A. (info symbol, human readable)
17-symbol-list-functions N.A. (info functions, human readable)
18-symbol-list-types N.A. (info types, human readable)
19-symbol-list-variables N.A. (info variables, human readable)
20-symbol-list-lines No (gdb 6.x)
21-symbol-locate N.A.
22-symbol-type N.A. (ptype, human readable)
23@</pre>
24
25Note:@p
26
27Only one is implemented and not in gdb 5.x.@p
28
29***************************************************************************/
30
31#include "gdbmi.h"
32
diff --git a/pathologist/src/mi/gdbmi_target_man.c b/pathologist/src/mi/gdbmi_target_man.c
new file mode 100644
index 0000000..bbb2b98
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_target_man.c
@@ -0,0 +1,119 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2007 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Target manipulation.
7 Comments:
8 GDB/MI commands for the "Target Manipulation" section. @<p>
9
10@<pre>
11-target-attach Yes (implemented using attach)
12-target-compare-sections N.A. (compare-sections)
13-target-detach Yes
14-target-download Yes
15-target-exec-status N.A.
16-target-list-available-targets N.A. (help target)
17-target-list-current-targets N.A. (info file among other things)
18-target-list-parameters N.A.
19-target-select Yes
20@</pre>
21
22***************************************************************************/
23
24#include "gdbmi.h"
25
26/* Low level versions. */
27
28void mi_target_select(mi_h *h, const char *type, const char *params)
29{
30 mi_send(h,"-target-select %s %s\n",type,params);
31}
32
33/* Note: -target-attach isn't currently implemented :-( (gdb 6.1.1) */
34void mi_target_attach(mi_h *h, pid_t pid)
35{
36 mi_send(h,"attach %d\n",pid);
37}
38
39void mi_target_detach(mi_h *h)
40{
41 mi_send(h,"-target-detach\n");
42}
43
44void mi_target_download(mi_h *h)
45{
46 mi_send(h,"-target-download\n");
47}
48
49/* High level versions. */
50
51/**[txh]********************************************************************
52
53 Description:
54 Connect to a remote gdbserver using the specified methode.
55
56 Command: -target-select
57 Return: !=0 OK
58
59***************************************************************************/
60
61int gmi_target_select(mi_h *h, const char *type, const char *params)
62{
63 mi_target_select(h,type,params);
64 if (!mi_res_simple_connected(h))
65 return 0;
66 mi_send_target_commands(h);
67 return 1;
68}
69
70/**[txh]********************************************************************
71
72 Description:
73 Attach to an already running process.
74
75 Command: -target-attach [using attach]
76 Return: The frame of the current location, NULL on error.
77
78***************************************************************************/
79
80mi_frames *gmi_target_attach(mi_h *h, pid_t pid)
81{
82 mi_target_attach(h,pid);
83 //return mi_res_simple_done(h);
84 return mi_res_frame(h);
85}
86
87/**[txh]********************************************************************
88
89 Description:
90 Detach from an attached process.
91
92 Command: -target-detach
93 Return: !=0 OK
94
95***************************************************************************/
96
97int gmi_target_detach(mi_h *h)
98{
99 mi_target_detach(h);
100 return mi_res_simple_done(h);
101}
102
103/**[txh]********************************************************************
104
105 Description:
106 Loads the executable onto the remote target.
107
108 Command: -target-download
109 Return: !=0 OK
110
111***************************************************************************/
112
113int gmi_target_download(mi_h *h)
114{
115 mi_target_download(h);
116 // TODO: this response have some data
117 return mi_res_simple_done(h);
118}
119
diff --git a/pathologist/src/mi/gdbmi_thread.c b/pathologist/src/mi/gdbmi_thread.c
new file mode 100644
index 0000000..b8fa63d
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_thread.c
@@ -0,0 +1,89 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Thread commands.
7 Comments:
8 GDB/MI commands for the "Thread Commands" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12-thread-info N.A.
13-thread-list-all-threads Yes, implemented as "info threads"
14-thread-list-ids Yes
15-thread-select Yes
16@</pre>
17
18***************************************************************************/
19
20#include "gdbmi.h"
21
22/* Low level versions. */
23
24void mi_thread_list_ids(mi_h *h)
25{
26 mi_send(h,"-thread-list-ids\n");
27}
28
29void mi_thread_select(mi_h *h, int id)
30{
31 mi_send(h,"-thread-select %d\n",id);
32}
33
34void mi_thread_list_all_threads(mi_h *h)
35{
36 mi_send(h,"info threads\n");
37}
38
39/* High level versions. */
40
41/**[txh]********************************************************************
42
43 Description:
44 List available thread ids.
45
46 Command: -thread-list-ids
47 Return: !=0 OK
48
49***************************************************************************/
50
51int gmi_thread_list_ids(mi_h *h, int **list)
52{
53 mi_thread_list_ids(h);
54 return mi_res_thread_ids(h,list);
55}
56
57/**[txh]********************************************************************
58
59 Description:
60 Select a thread.
61
62 Command: -thread-select
63 Return: A new mi_frames or NULL on error.
64
65***************************************************************************/
66
67mi_frames *gmi_thread_select(mi_h *h, int id)
68{
69 mi_thread_select(h,id);
70 return mi_res_frame(h);
71}
72
73/**[txh]********************************************************************
74
75 Description:
76 Get a list of frames for each available thread. Implemented using "info
77thread".
78
79 Command: -thread-list-all-threads
80 Return: A kist of frames, NULL on error
81
82***************************************************************************/
83
84mi_frames *gmi_thread_list_all_threads(mi_h *h)
85{
86 mi_thread_list_all_threads(h);
87 return mi_res_frames_list(h);
88}
89
diff --git a/pathologist/src/mi/gdbmi_var_obj.c b/pathologist/src/mi/gdbmi_var_obj.c
new file mode 100644
index 0000000..435feec
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_var_obj.c
@@ -0,0 +1,371 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Variable objects.
7 Comments:
8 GDB/MI commands for the "Variable Objects" section.
9 @<p>
10
11@<pre>
12gdb command: Imp? Description:
13-var-create Yes create a variable object
14-var-delete Yes delete the variable object and its children
15-var-set-format Yes set the display format of this variable
16-var-show-format Yes show the display format of this variable
17-var-info-num-children Yes tells how many children this object has
18-var-list-children Yes* return a list of the object's children
19-var-info-type Yes show the type of this variable object
20-var-info-expression Yes print what this variable object represents
21-var-show-attributes Yes is this variable editable?
22-var-evaluate-expression Yes get the value of this variable
23-var-assign Yes set the value of this variable
24-var-update Yes* update the variable and its children
25@</pre>
26
27Notes: @<p>
281) I suggest letting gdb to choose the names for the variables.@*
292) -var-list-children supports an optional "show values" argument in MI v2.
30It isn't implemented.@*
31
32 @<p>
33
34* MI v1 and v2 result formats supported. @<p>
35
36***************************************************************************/
37
38#include "gdbmi.h"
39
40/* Low level versions. */
41
42void mi_var_create(mi_h *h, const char *name, int frame, const char *exp)
43{
44 const char *n=name ? name : "-";
45
46 if (frame<0)
47 mi_send(h,"-var-create %s * %s\n",n,exp);
48 else
49 mi_send(h,"-var-create %s %d %s\n",n,frame,exp);
50}
51
52void mi_var_delete(mi_h *h, const char *name)
53{
54 mi_send(h,"-var-delete %s\n",name);
55}
56
57void mi_var_set_format(mi_h *h, const char *name, const char *format)
58{
59 mi_send(h,"-var-set-format \"%s\" %s\n",name,format);
60}
61
62void mi_var_show_format(mi_h *h, const char *name)
63{
64 mi_send(h,"-var-show-format \"%s\"\n",name);
65}
66
67void mi_var_info_num_children(mi_h *h, const char *name)
68{
69 mi_send(h,"-var-info-num-children \"%s\"\n",name);
70}
71
72void mi_var_info_type(mi_h *h, const char *name)
73{
74 mi_send(h,"-var-info-type \"%s\"\n",name);
75}
76
77void mi_var_info_expression(mi_h *h, const char *name)
78{
79 mi_send(h,"-var-info-expression \"%s\"\n",name);
80}
81
82void mi_var_show_attributes(mi_h *h, const char *name)
83{
84 mi_send(h,"-var-show-attributes \"%s\"\n",name);
85}
86
87void mi_var_update(mi_h *h, const char *name)
88{
89 if (name)
90 mi_send(h,"-var-update %s\n",name);
91 else
92 mi_send(h,"-var-update *\n");
93}
94
95void mi_var_assign(mi_h *h, const char *name, const char *expression)
96{
97 mi_send(h,"-var-assign \"%s\" \"%s\"\n",name,expression);
98}
99
100void mi_var_evaluate_expression(mi_h *h, const char *name)
101{
102 mi_send(h,"-var-evaluate-expression \"%s\"\n",name);
103}
104
105void mi_var_list_children(mi_h *h, const char *name)
106{
107 if (h->version>=MI_VERSION2U(2,0,0))
108 mi_send(h,"-var-list-children --all-values \"%s\"\n",name);
109 else
110 mi_send(h,"-var-list-children \"%s\"\n",name);
111}
112
113/* High level versions. */
114
115/**[txh]********************************************************************
116
117 Description:
118 Create a variable object. I recommend using gmi_var_create and letting
119gdb choose the names.
120
121 Command: -var-create
122 Return: A new mi_gvar strcture or NULL on error.
123
124***************************************************************************/
125
126mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp)
127{
128 mi_var_create(h,name,frame,exp);
129 return mi_res_gvar(h,NULL,exp);
130}
131
132/**[txh]********************************************************************
133
134 Description:
135 Create a variable object. The name is selected by gdb. Alternative:
136 gmi_full_var_create.
137
138 Command: -var-create [auto name]
139 Return: A new mi_gvar strcture or NULL on error.
140
141***************************************************************************/
142
143mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp)
144{
145 return gmi_var_create_nm(h,NULL,frame,exp);
146}
147
148/**[txh]********************************************************************
149
150 Description:
151 Delete a variable object. Doesn't free the mi_gvar data.
152
153 Command: -var-delete
154 Return: !=0 OK
155
156***************************************************************************/
157
158int gmi_var_delete(mi_h *h, mi_gvar *var)
159{
160 mi_var_delete(h,var->name);
161 return mi_res_simple_done(h);
162}
163
164/**[txh]********************************************************************
165
166 Description:
167 Set the format used to represent the result.
168
169 Command: -var-set-format
170 Return: !=0 OK
171
172***************************************************************************/
173
174int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format)
175{
176 int ret;
177
178 mi_var_set_format(h,var->name,mi_format_enum_to_str(format));
179 ret=mi_res_simple_done(h);
180 if (ret)
181 var->format=format;
182 return ret;
183}
184
185/**[txh]********************************************************************
186
187 Description:
188 Fill the format field with info from gdb.
189
190 Command: -var-show-format
191 Return: !=0 OK.
192
193***************************************************************************/
194
195int gmi_var_show_format(mi_h *h, mi_gvar *var)
196{
197 mi_var_show_format(h,var->name);
198 return mi_res_gvar(h,var,NULL)!=NULL;
199}
200
201/**[txh]********************************************************************
202
203 Description:
204 Fill the numchild field with info from gdb.
205
206 Command: -var-info-num-children
207 Return: !=0 OK
208
209***************************************************************************/
210
211int gmi_var_info_num_children(mi_h *h, mi_gvar *var)
212{
213 mi_var_info_num_children(h,var->name);
214 return mi_res_gvar(h,var,NULL)!=NULL;
215}
216
217/**[txh]********************************************************************
218
219 Description:
220 Fill the type field with info from gdb.
221
222 Command: -var-info-type
223 Return: !=0 OK
224
225***************************************************************************/
226
227int gmi_var_info_type(mi_h *h, mi_gvar *var)
228{
229 mi_var_info_type(h,var->name);
230 return mi_res_gvar(h,var,NULL)!=NULL;
231}
232
233/**[txh]********************************************************************
234
235 Description:
236 Fill the expression and lang fields with info from gdb. Note that lang
237isn't filled during creation.
238
239 Command: -var-info-expression
240 Return: !=0 OK
241
242***************************************************************************/
243
244int gmi_var_info_expression(mi_h *h, mi_gvar *var)
245{
246 mi_var_info_expression(h,var->name);
247 return mi_res_gvar(h,var,NULL)!=NULL;
248}
249
250
251/**[txh]********************************************************************
252
253 Description:
254 Fill the attr field with info from gdb. Note that attr isn't filled
255during creation.
256
257 Command: -var-show-attributes
258 Return: !=0 OK
259
260***************************************************************************/
261
262int gmi_var_show_attributes(mi_h *h, mi_gvar *var)
263{
264 mi_var_show_attributes(h,var->name);
265 return mi_res_gvar(h,var,NULL)!=NULL;
266}
267
268/**[txh]********************************************************************
269
270 Description:
271 Create the variable and also fill the lang and attr fields. The name is
272selected by gdb.
273
274 Command: -var-create + -var-info-expression + -var-show-attributes
275 Return: A new mi_gvar strcture or NULL on error.
276
277***************************************************************************/
278
279mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp)
280{
281 mi_gvar *var=gmi_var_create_nm(h,NULL,frame,exp);
282 if (var)
283 {/* What if it fails? */
284 gmi_var_info_expression(h,var);
285 gmi_var_show_attributes(h,var);
286 }
287 return var;
288}
289
290/**[txh]********************************************************************
291
292 Description:
293 Update variable. Use NULL for all. Note that *changed can be NULL if none
294updated.
295
296 Command: -var-update
297 Return: !=0 OK. The changed list contains the list of changed vars.
298
299***************************************************************************/
300
301int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed)
302{
303 mi_var_update(h,var ? var->name : NULL);
304 return mi_res_changelist(h,changed);
305}
306
307/**[txh]********************************************************************
308
309 Description:
310 Change variable. The new value replaces the value field.
311
312 Command: -var-assign
313 Return: !=0 OK
314
315***************************************************************************/
316
317int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression)
318{
319 char *res;
320 mi_var_assign(h,var->name,expression);
321 res=mi_res_value(h);
322 if (res)
323 {
324 free(var->value);
325 var->value=res;
326 return 1;
327 }
328 return 0;
329}
330
331/**[txh]********************************************************************
332
333 Description:
334 Fill the value field getting the current value for a variable.
335
336 Command: -var-evaluate-expression
337 Return: !=0 OK, value contains the result.
338
339***************************************************************************/
340
341int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var)
342{
343 char *s;
344
345 mi_var_evaluate_expression(h,var->name);
346 s=mi_res_value(h);
347 if (s)
348 {
349 free(var->value);
350 var->value=s;
351 }
352 return s!=NULL;
353}
354
355/**[txh]********************************************************************
356
357 Description:
358 List children. It ONLY returns the first level information. :-(@*
359 On success the child field contains the list of children.
360
361 Command: -var-list-children
362 Return: !=0 OK
363
364***************************************************************************/
365
366int gmi_var_list_children(mi_h *h, mi_gvar *var)
367{
368 mi_var_list_children(h,var->name);
369 return mi_res_children(h,var);
370}
371
diff --git a/pathologist/src/minixml/Makefile.am b/pathologist/src/minixml/Makefile.am
new file mode 100644
index 0000000..423fbdc
--- /dev/null
+++ b/pathologist/src/minixml/Makefile.am
@@ -0,0 +1,27 @@
1INCLUDES = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage -O0
9 XLIB = -lgcov
10endif
11
12lib_LTLIBRARIES = libminixml.la
13
14libminixml_la_SOURCES = \
15 mxml-attr.c \
16 mxmldoc.c \
17 mxml-entity.c \
18 mxml-file.c \
19 mxml-get.c \
20 mxml-index.c \
21 mxml-node.c \
22 mxml-private.c \
23 mxml-private.h \
24 mxml-search.c \
25 mxml-set.c \
26 mxml-string.c \
27 config.h \ No newline at end of file
diff --git a/pathologist/src/minixml/config.h b/pathologist/src/minixml/config.h
new file mode 100644
index 0000000..8bae4bf
--- /dev/null
+++ b/pathologist/src/minixml/config.h
@@ -0,0 +1,95 @@
1/*
2 * "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $"
3 *
4 * Configuration file for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 */
16
17/*
18 * Include necessary headers...
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <stdarg.h>
25#include <ctype.h>
26
27
28/*
29 * Version number...
30 */
31
32#define MXML_VERSION ""
33
34
35/*
36 * Inline function support...
37 */
38
39#define inline
40
41
42/*
43 * Long long support...
44 */
45
46#undef HAVE_LONG_LONG
47
48
49/*
50 * Do we have the snprintf() and vsnprintf() functions?
51 */
52
53#undef HAVE_SNPRINTF
54#undef HAVE_VSNPRINTF
55
56
57/*
58 * Do we have the strXXX() functions?
59 */
60
61#undef HAVE_STRDUP
62
63
64/*
65 * Do we have threading support?
66 */
67
68#undef HAVE_PTHREAD_H
69
70
71/*
72 * Define prototypes for string functions as needed...
73 */
74
75# ifndef HAVE_STRDUP
76extern char *_mxml_strdup(const char *);
77# define strdup _mxml_strdup
78# endif /* !HAVE_STRDUP */
79
80extern char *_mxml_strdupf(const char *, ...);
81extern char *_mxml_vstrdupf(const char *, va_list);
82
83# ifndef HAVE_SNPRINTF
84extern int _mxml_snprintf(char *, size_t, const char *, ...);
85# define snprintf _mxml_snprintf
86# endif /* !HAVE_SNPRINTF */
87
88# ifndef HAVE_VSNPRINTF
89extern int _mxml_vsnprintf(char *, size_t, const char *, va_list);
90# define vsnprintf _mxml_vsnprintf
91# endif /* !HAVE_VSNPRINTF */
92
93/*
94 * End of "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $".
95 */
diff --git a/pathologist/src/minixml/mxml-attr.c b/pathologist/src/minixml/mxml-attr.c
new file mode 100644
index 0000000..c9950f5
--- /dev/null
+++ b/pathologist/src/minixml/mxml-attr.c
@@ -0,0 +1,319 @@
1/*
2 * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
3 *
4 * Attribute support code for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlElementDeleteAttr() - Delete an attribute.
19 * mxmlElementGetAttr() - Get an attribute.
20 * mxmlElementSetAttr() - Set an attribute.
21 * mxmlElementSetAttrf() - Set an attribute with a formatted value.
22 * mxml_set_attr() - Set or add an attribute name/value pair.
23 */
24
25/*
26 * Include necessary headers...
27 */
28
29#include "config.h"
30#include "mxml.h"
31
32
33/*
34 * Local functions...
35 */
36
37static int mxml_set_attr(mxml_node_t *node, const char *name,
38 char *value);
39
40
41/*
42 * 'mxmlElementDeleteAttr()' - Delete an attribute.
43 *
44 * @since Mini-XML 2.4@
45 */
46
47void
48mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
49 const char *name)/* I - Attribute name */
50{
51 int i; /* Looping var */
52 mxml_attr_t *attr; /* Cirrent attribute */
53
54
55#ifdef DEBUG
56 fprintf(stderr, "mxmlElementDeleteAttr(node=%p, name=\"%s\")\n",
57 node, name ? name : "(null)");
58#endif /* DEBUG */
59
60 /*
61 * Range check input...
62 */
63
64 if (!node || node->type != MXML_ELEMENT || !name)
65 return;
66
67 /*
68 * Look for the attribute...
69 */
70
71 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
72 i > 0;
73 i --, attr ++)
74 {
75#ifdef DEBUG
76 printf(" %s=\"%s\"\n", attr->name, attr->value);
77#endif /* DEBUG */
78
79 if (!strcmp(attr->name, name))
80 {
81 /*
82 * Delete this attribute...
83 */
84
85 free(attr->name);
86 free(attr->value);
87
88 i --;
89 if (i > 0)
90 memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
91
92 node->value.element.num_attrs --;
93 return;
94 }
95 }
96}
97
98
99/*
100 * 'mxmlElementGetAttr()' - Get an attribute.
101 *
102 * This function returns NULL if the node is not an element or the
103 * named attribute does not exist.
104 */
105
106const char * /* O - Attribute value or NULL */
107mxmlElementGetAttr(mxml_node_t *node, /* I - Element node */
108 const char *name) /* I - Name of attribute */
109{
110 int i; /* Looping var */
111 mxml_attr_t *attr; /* Cirrent attribute */
112
113
114#ifdef DEBUG
115 fprintf(stderr, "mxmlElementGetAttr(node=%p, name=\"%s\")\n",
116 node, name ? name : "(null)");
117#endif /* DEBUG */
118
119 /*
120 * Range check input...
121 */
122
123 if (!node || node->type != MXML_ELEMENT || !name)
124 return (NULL);
125
126 /*
127 * Look for the attribute...
128 */
129
130 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
131 i > 0;
132 i --, attr ++)
133 {
134#ifdef DEBUG
135 printf(" %s=\"%s\"\n", attr->name, attr->value);
136#endif /* DEBUG */
137
138 if (!strcmp(attr->name, name))
139 {
140#ifdef DEBUG
141 printf(" Returning \"%s\"!\n", attr->value);
142#endif /* DEBUG */
143 return (attr->value);
144 }
145 }
146
147 /*
148 * Didn't find attribute, so return NULL...
149 */
150
151#ifdef DEBUG
152 puts(" Returning NULL!\n");
153#endif /* DEBUG */
154
155 return (NULL);
156}
157
158
159/*
160 * 'mxmlElementSetAttr()' - Set an attribute.
161 *
162 * If the named attribute already exists, the value of the attribute
163 * is replaced by the new string value. The string value is copied
164 * into the element node. This function does nothing if the node is
165 * not an element.
166 */
167
168void
169mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
170 const char *name, /* I - Name of attribute */
171 const char *value) /* I - Attribute value */
172{
173 char *valuec; /* Copy of value */
174
175
176#ifdef DEBUG
177 fprintf(stderr, "mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n",
178 node, name ? name : "(null)", value ? value : "(null)");
179#endif /* DEBUG */
180
181 /*
182 * Range check input...
183 */
184
185 if (!node || node->type != MXML_ELEMENT || !name)
186 return;
187
188 if (value)
189 valuec = strdup(value);
190 else
191 valuec = NULL;
192
193 if (mxml_set_attr(node, name, valuec))
194 free(valuec);
195}
196
197
198/*
199 * 'mxmlElementSetAttrf()' - Set an attribute with a formatted value.
200 *
201 * If the named attribute already exists, the value of the attribute
202 * is replaced by the new formatted string. The formatted string value is
203 * copied into the element node. This function does nothing if the node
204 * is not an element.
205 *
206 * @since Mini-XML 2.3@
207 */
208
209void
210mxmlElementSetAttrf(mxml_node_t *node, /* I - Element node */
211 const char *name, /* I - Name of attribute */
212 const char *format,/* I - Printf-style attribute value */
213 ...) /* I - Additional arguments as needed */
214{
215 va_list ap; /* Argument pointer */
216 char *value; /* Value */
217
218
219#ifdef DEBUG
220 fprintf(stderr,
221 "mxmlElementSetAttrf(node=%p, name=\"%s\", format=\"%s\", ...)\n",
222 node, name ? name : "(null)", format ? format : "(null)");
223#endif /* DEBUG */
224
225 /*
226 * Range check input...
227 */
228
229 if (!node || node->type != MXML_ELEMENT || !name || !format)
230 return;
231
232 /*
233 * Format the value...
234 */
235
236 va_start(ap, format);
237 value = _mxml_vstrdupf(format, ap);
238 va_end(ap);
239
240 if (!value)
241 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
242 name, node->value.element.name);
243 else if (mxml_set_attr(node, name, value))
244 free(value);
245}
246
247
248/*
249 * 'mxml_set_attr()' - Set or add an attribute name/value pair.
250 */
251
252static int /* O - 0 on success, -1 on failure */
253mxml_set_attr(mxml_node_t *node, /* I - Element node */
254 const char *name, /* I - Attribute name */
255 char *value) /* I - Attribute value */
256{
257 int i; /* Looping var */
258 mxml_attr_t *attr; /* New attribute */
259
260
261 /*
262 * Look for the attribute...
263 */
264
265 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
266 i > 0;
267 i --, attr ++)
268 if (!strcmp(attr->name, name))
269 {
270 /*
271 * Free the old value as needed...
272 */
273
274 if (attr->value)
275 free(attr->value);
276
277 attr->value = value;
278
279 return (0);
280 }
281
282 /*
283 * Add a new attribute...
284 */
285
286 if (node->value.element.num_attrs == 0)
287 attr = malloc(sizeof(mxml_attr_t));
288 else
289 attr = realloc(node->value.element.attrs,
290 (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));
291
292 if (!attr)
293 {
294 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
295 name, node->value.element.name);
296 return (-1);
297 }
298
299 node->value.element.attrs = attr;
300 attr += node->value.element.num_attrs;
301
302 if ((attr->name = strdup(name)) == NULL)
303 {
304 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
305 name, node->value.element.name);
306 return (-1);
307 }
308
309 attr->value = value;
310
311 node->value.element.num_attrs ++;
312
313 return (0);
314}
315
316
317/*
318 * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
319 */
diff --git a/pathologist/src/minixml/mxml-entity.c b/pathologist/src/minixml/mxml-entity.c
new file mode 100644
index 0000000..c5c9f61
--- /dev/null
+++ b/pathologist/src/minixml/mxml-entity.c
@@ -0,0 +1,460 @@
1/*
2 * "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $"
3 *
4 * Character entity support code for Mini-XML, a small XML-like
5 * file parsing library.
6 *
7 * Copyright 2003-2010 by Michael R Sweet.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Michael R Sweet and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "COPYING"
12 * which should have been included with this file. If this file is
13 * missing or damaged, see the license at:
14 *
15 * http://www.minixml.org/
16 *
17 * Contents:
18 *
19 * mxmlEntityAddCallback() - Add a callback to convert entities to
20 * Unicode.
21 * mxmlEntityGetName() - Get the name that corresponds to the
22 * character value.
23 * mxmlEntityGetValue() - Get the character corresponding to a named
24 * entity.
25 * mxmlEntityRemoveCallback() - Remove a callback.
26 * _mxml_entity_cb() - Lookup standard (X)HTML entities.
27 */
28
29/*
30 * Include necessary headers...
31 */
32
33#include "mxml-private.h"
34
35
36/*
37 * 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
38 */
39
40int /* O - 0 on success, -1 on failure */
41mxmlEntityAddCallback(
42 mxml_entity_cb_t cb) /* I - Callback function to add */
43{
44 _mxml_global_t *global = _mxml_global();
45 /* Global data */
46
47
48 if (global->num_entity_cbs < (int)(sizeof(global->entity_cbs) / sizeof(global->entity_cbs[0])))
49 {
50 global->entity_cbs[global->num_entity_cbs] = cb;
51 global->num_entity_cbs ++;
52
53 return (0);
54 }
55 else
56 {
57 mxml_error("Unable to add entity callback!");
58
59 return (-1);
60 }
61}
62
63
64/*
65 * 'mxmlEntityGetName()' - Get the name that corresponds to the character value.
66 *
67 * If val does not need to be represented by a named entity, NULL is returned.
68 */
69
70const char * /* O - Entity name or NULL */
71mxmlEntityGetName(int val) /* I - Character value */
72{
73 switch (val)
74 {
75 case '&' :
76 return ("amp");
77
78 case '<' :
79 return ("lt");
80
81 case '>' :
82 return ("gt");
83
84 case '\"' :
85 return ("quot");
86
87 default :
88 return (NULL);
89 }
90}
91
92
93/*
94 * 'mxmlEntityGetValue()' - Get the character corresponding to a named entity.
95 *
96 * The entity name can also be a numeric constant. -1 is returned if the
97 * name is not known.
98 */
99
100int /* O - Character value or -1 on error */
101mxmlEntityGetValue(const char *name) /* I - Entity name */
102{
103 int i; /* Looping var */
104 int ch; /* Character value */
105 _mxml_global_t *global = _mxml_global();
106 /* Global data */
107
108
109 for (i = 0; i < global->num_entity_cbs; i ++)
110 if ((ch = (global->entity_cbs[i])(name)) >= 0)
111 return (ch);
112
113 return (-1);
114}
115
116
117/*
118 * 'mxmlEntityRemoveCallback()' - Remove a callback.
119 */
120
121void
122mxmlEntityRemoveCallback(
123 mxml_entity_cb_t cb) /* I - Callback function to remove */
124{
125 int i; /* Looping var */
126 _mxml_global_t *global = _mxml_global();
127 /* Global data */
128
129
130 for (i = 0; i < global->num_entity_cbs; i ++)
131 if (cb == global->entity_cbs[i])
132 {
133 /*
134 * Remove the callback...
135 */
136
137 global->num_entity_cbs --;
138
139 if (i < global->num_entity_cbs)
140 memmove(global->entity_cbs + i, global->entity_cbs + i + 1,
141 (global->num_entity_cbs - i) * sizeof(global->entity_cbs[0]));
142
143 return;
144 }
145}
146
147
148/*
149 * '_mxml_entity_cb()' - Lookup standard (X)HTML entities.
150 */
151
152int /* O - Unicode value or -1 */
153_mxml_entity_cb(const char *name) /* I - Entity name */
154{
155 int diff, /* Difference between names */
156 current, /* Current entity in search */
157 first, /* First entity in search */
158 last; /* Last entity in search */
159 static const struct
160 {
161 const char *name; /* Entity name */
162 int val; /* Character value */
163 } entities[] =
164 {
165 { "AElig", 198 },
166 { "Aacute", 193 },
167 { "Acirc", 194 },
168 { "Agrave", 192 },
169 { "Alpha", 913 },
170 { "Aring", 197 },
171 { "Atilde", 195 },
172 { "Auml", 196 },
173 { "Beta", 914 },
174 { "Ccedil", 199 },
175 { "Chi", 935 },
176 { "Dagger", 8225 },
177 { "Delta", 916 },
178 { "Dstrok", 208 },
179 { "ETH", 208 },
180 { "Eacute", 201 },
181 { "Ecirc", 202 },
182 { "Egrave", 200 },
183 { "Epsilon", 917 },
184 { "Eta", 919 },
185 { "Euml", 203 },
186 { "Gamma", 915 },
187 { "Iacute", 205 },
188 { "Icirc", 206 },
189 { "Igrave", 204 },
190 { "Iota", 921 },
191 { "Iuml", 207 },
192 { "Kappa", 922 },
193 { "Lambda", 923 },
194 { "Mu", 924 },
195 { "Ntilde", 209 },
196 { "Nu", 925 },
197 { "OElig", 338 },
198 { "Oacute", 211 },
199 { "Ocirc", 212 },
200 { "Ograve", 210 },
201 { "Omega", 937 },
202 { "Omicron", 927 },
203 { "Oslash", 216 },
204 { "Otilde", 213 },
205 { "Ouml", 214 },
206 { "Phi", 934 },
207 { "Pi", 928 },
208 { "Prime", 8243 },
209 { "Psi", 936 },
210 { "Rho", 929 },
211 { "Scaron", 352 },
212 { "Sigma", 931 },
213 { "THORN", 222 },
214 { "Tau", 932 },
215 { "Theta", 920 },
216 { "Uacute", 218 },
217 { "Ucirc", 219 },
218 { "Ugrave", 217 },
219 { "Upsilon", 933 },
220 { "Uuml", 220 },
221 { "Xi", 926 },
222 { "Yacute", 221 },
223 { "Yuml", 376 },
224 { "Zeta", 918 },
225 { "aacute", 225 },
226 { "acirc", 226 },
227 { "acute", 180 },
228 { "aelig", 230 },
229 { "agrave", 224 },
230 { "alefsym", 8501 },
231 { "alpha", 945 },
232 { "amp", '&' },
233 { "and", 8743 },
234 { "ang", 8736 },
235 { "apos", '\'' },
236 { "aring", 229 },
237 { "asymp", 8776 },
238 { "atilde", 227 },
239 { "auml", 228 },
240 { "bdquo", 8222 },
241 { "beta", 946 },
242 { "brkbar", 166 },
243 { "brvbar", 166 },
244 { "bull", 8226 },
245 { "cap", 8745 },
246 { "ccedil", 231 },
247 { "cedil", 184 },
248 { "cent", 162 },
249 { "chi", 967 },
250 { "circ", 710 },
251 { "clubs", 9827 },
252 { "cong", 8773 },
253 { "copy", 169 },
254 { "crarr", 8629 },
255 { "cup", 8746 },
256 { "curren", 164 },
257 { "dArr", 8659 },
258 { "dagger", 8224 },
259 { "darr", 8595 },
260 { "deg", 176 },
261 { "delta", 948 },
262 { "diams", 9830 },
263 { "die", 168 },
264 { "divide", 247 },
265 { "eacute", 233 },
266 { "ecirc", 234 },
267 { "egrave", 232 },
268 { "empty", 8709 },
269 { "emsp", 8195 },
270 { "ensp", 8194 },
271 { "epsilon", 949 },
272 { "equiv", 8801 },
273 { "eta", 951 },
274 { "eth", 240 },
275 { "euml", 235 },
276 { "euro", 8364 },
277 { "exist", 8707 },
278 { "fnof", 402 },
279 { "forall", 8704 },
280 { "frac12", 189 },
281 { "frac14", 188 },
282 { "frac34", 190 },
283 { "frasl", 8260 },
284 { "gamma", 947 },
285 { "ge", 8805 },
286 { "gt", '>' },
287 { "hArr", 8660 },
288 { "harr", 8596 },
289 { "hearts", 9829 },
290 { "hellip", 8230 },
291 { "hibar", 175 },
292 { "iacute", 237 },
293 { "icirc", 238 },
294 { "iexcl", 161 },
295 { "igrave", 236 },
296 { "image", 8465 },
297 { "infin", 8734 },
298 { "int", 8747 },
299 { "iota", 953 },
300 { "iquest", 191 },
301 { "isin", 8712 },
302 { "iuml", 239 },
303 { "kappa", 954 },
304 { "lArr", 8656 },
305 { "lambda", 955 },
306 { "lang", 9001 },
307 { "laquo", 171 },
308 { "larr", 8592 },
309 { "lceil", 8968 },
310 { "ldquo", 8220 },
311 { "le", 8804 },
312 { "lfloor", 8970 },
313 { "lowast", 8727 },
314 { "loz", 9674 },
315 { "lrm", 8206 },
316 { "lsaquo", 8249 },
317 { "lsquo", 8216 },
318 { "lt", '<' },
319 { "macr", 175 },
320 { "mdash", 8212 },
321 { "micro", 181 },
322 { "middot", 183 },
323 { "minus", 8722 },
324 { "mu", 956 },
325 { "nabla", 8711 },
326 { "nbsp", 160 },
327 { "ndash", 8211 },
328 { "ne", 8800 },
329 { "ni", 8715 },
330 { "not", 172 },
331 { "notin", 8713 },
332 { "nsub", 8836 },
333 { "ntilde", 241 },
334 { "nu", 957 },
335 { "oacute", 243 },
336 { "ocirc", 244 },
337 { "oelig", 339 },
338 { "ograve", 242 },
339 { "oline", 8254 },
340 { "omega", 969 },
341 { "omicron", 959 },
342 { "oplus", 8853 },
343 { "or", 8744 },
344 { "ordf", 170 },
345 { "ordm", 186 },
346 { "oslash", 248 },
347 { "otilde", 245 },
348 { "otimes", 8855 },
349 { "ouml", 246 },
350 { "para", 182 },
351 { "part", 8706 },
352 { "permil", 8240 },
353 { "perp", 8869 },
354 { "phi", 966 },
355 { "pi", 960 },
356 { "piv", 982 },
357 { "plusmn", 177 },
358 { "pound", 163 },
359 { "prime", 8242 },
360 { "prod", 8719 },
361 { "prop", 8733 },
362 { "psi", 968 },
363 { "quot", '\"' },
364 { "rArr", 8658 },
365 { "radic", 8730 },
366 { "rang", 9002 },
367 { "raquo", 187 },
368 { "rarr", 8594 },
369 { "rceil", 8969 },
370 { "rdquo", 8221 },
371 { "real", 8476 },
372 { "reg", 174 },
373 { "rfloor", 8971 },
374 { "rho", 961 },
375 { "rlm", 8207 },
376 { "rsaquo", 8250 },
377 { "rsquo", 8217 },
378 { "sbquo", 8218 },
379 { "scaron", 353 },
380 { "sdot", 8901 },
381 { "sect", 167 },
382 { "shy", 173 },
383 { "sigma", 963 },
384 { "sigmaf", 962 },
385 { "sim", 8764 },
386 { "spades", 9824 },
387 { "sub", 8834 },
388 { "sube", 8838 },
389 { "sum", 8721 },
390 { "sup", 8835 },
391 { "sup1", 185 },
392 { "sup2", 178 },
393 { "sup3", 179 },
394 { "supe", 8839 },
395 { "szlig", 223 },
396 { "tau", 964 },
397 { "there4", 8756 },
398 { "theta", 952 },
399 { "thetasym", 977 },
400 { "thinsp", 8201 },
401 { "thorn", 254 },
402 { "tilde", 732 },
403 { "times", 215 },
404 { "trade", 8482 },
405 { "uArr", 8657 },
406 { "uacute", 250 },
407 { "uarr", 8593 },
408 { "ucirc", 251 },
409 { "ugrave", 249 },
410 { "uml", 168 },
411 { "upsih", 978 },
412 { "upsilon", 965 },
413 { "uuml", 252 },
414 { "weierp", 8472 },
415 { "xi", 958 },
416 { "yacute", 253 },
417 { "yen", 165 },
418 { "yuml", 255 },
419 { "zeta", 950 },
420 { "zwj", 8205 },
421 { "zwnj", 8204 }
422 };
423
424
425 /*
426 * Do a binary search for the named entity...
427 */
428
429 first = 0;
430 last = (int)(sizeof(entities) / sizeof(entities[0]) - 1);
431
432 while ((last - first) > 1)
433 {
434 current = (first + last) / 2;
435
436 if ((diff = strcmp(name, entities[current].name)) == 0)
437 return (entities[current].val);
438 else if (diff < 0)
439 last = current;
440 else
441 first = current;
442 }
443
444 /*
445 * If we get here, there is a small chance that there is still
446 * a match; check first and last...
447 */
448
449 if (!strcmp(name, entities[first].name))
450 return (entities[first].val);
451 else if (!strcmp(name, entities[last].name))
452 return (entities[last].val);
453 else
454 return (-1);
455}
456
457
458/*
459 * End of "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $".
460 */
diff --git a/pathologist/src/minixml/mxml-file.c b/pathologist/src/minixml/mxml-file.c
new file mode 100644
index 0000000..9927040
--- /dev/null
+++ b/pathologist/src/minixml/mxml-file.c
@@ -0,0 +1,3080 @@
1/*
2 * "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $"
3 *
4 * File loading code for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2011 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlLoadFd() - Load a file descriptor into an XML node tree.
19 * mxmlLoadFile() - Load a file into an XML node tree.
20 * mxmlLoadString() - Load a string into an XML node tree.
21 * mxmlSaveAllocString() - Save an XML tree to an allocated string.
22 * mxmlSaveFd() - Save an XML tree to a file descriptor.
23 * mxmlSaveFile() - Save an XML tree to a file.
24 * mxmlSaveString() - Save an XML node tree to a string.
25 * mxmlSAXLoadFd() - Load a file descriptor into an XML node tree
26 * using a SAX callback.
27 * mxmlSAXLoadFile() - Load a file into an XML node tree
28 * using a SAX callback.
29 * mxmlSAXLoadString() - Load a string into an XML node tree
30 * using a SAX callback.
31 * mxmlSetCustomHandlers() - Set the handling functions for custom data.
32 * mxmlSetErrorCallback() - Set the error message callback.
33 * mxmlSetWrapMargin() - Set the wrap margin when saving XML data.
34 * mxml_add_char() - Add a character to a buffer, expanding as needed.
35 * mxml_fd_getc() - Read a character from a file descriptor.
36 * mxml_fd_putc() - Write a character to a file descriptor.
37 * mxml_fd_read() - Read a buffer of data from a file descriptor.
38 * mxml_fd_write() - Write a buffer of data to a file descriptor.
39 * mxml_file_getc() - Get a character from a file.
40 * mxml_file_putc() - Write a character to a file.
41 * mxml_get_entity() - Get the character corresponding to an entity...
42 * mxml_load_data() - Load data into an XML node tree.
43 * mxml_parse_element() - Parse an element for any attributes...
44 * mxml_string_getc() - Get a character from a string.
45 * mxml_string_putc() - Write a character to a string.
46 * mxml_write_name() - Write a name string.
47 * mxml_write_node() - Save an XML node to a file.
48 * mxml_write_string() - Write a string, escaping & and < as needed.
49 * mxml_write_ws() - Do whitespace callback...
50 */
51
52/*
53 * Include necessary headers...
54 */
55
56#ifndef WIN32
57# include <unistd.h>
58#endif /* !WIN32 */
59#include "mxml-private.h"
60
61
62/*
63 * Character encoding...
64 */
65
66#define ENCODE_UTF8 0 /* UTF-8 */
67#define ENCODE_UTF16BE 1 /* UTF-16 Big-Endian */
68#define ENCODE_UTF16LE 2 /* UTF-16 Little-Endian */
69
70
71/*
72 * Macro to test for a bad XML character...
73 */
74
75#define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) != '\t')
76
77
78/*
79 * Types and structures...
80 */
81
82typedef int (*_mxml_getc_cb_t)(void *, int *);
83typedef int (*_mxml_putc_cb_t)(int, void *);
84
85typedef struct _mxml_fdbuf_s /**** File descriptor buffer ****/
86{
87 int fd; /* File descriptor */
88 unsigned char *current, /* Current position in buffer */
89 *end, /* End of buffer */
90 buffer[8192]; /* Character buffer */
91} _mxml_fdbuf_t;
92
93
94/*
95 * Local functions...
96 */
97
98static int mxml_add_char(int ch, char **ptr, char **buffer,
99 int *bufsize);
100static int mxml_fd_getc(void *p, int *encoding);
101static int mxml_fd_putc(int ch, void *p);
102static int mxml_fd_read(_mxml_fdbuf_t *buf);
103static int mxml_fd_write(_mxml_fdbuf_t *buf);
104static int mxml_file_getc(void *p, int *encoding);
105static int mxml_file_putc(int ch, void *p);
106static int mxml_get_entity(mxml_node_t *parent, void *p,
107 int *encoding,
108 _mxml_getc_cb_t getc_cb);
109static inline int mxml_isspace(int ch)
110 {
111 return (ch == ' ' || ch == '\t' || ch == '\r' ||
112 ch == '\n');
113 }
114static mxml_node_t *mxml_load_data(mxml_node_t *top, void *p,
115 mxml_load_cb_t cb,
116 _mxml_getc_cb_t getc_cb,
117 mxml_sax_cb_t sax_cb, void *sax_data);
118static int mxml_parse_element(mxml_node_t *node, void *p,
119 int *encoding,
120 _mxml_getc_cb_t getc_cb);
121static int mxml_string_getc(void *p, int *encoding);
122static int mxml_string_putc(int ch, void *p);
123static int mxml_write_name(const char *s, void *p,
124 _mxml_putc_cb_t putc_cb);
125static int mxml_write_node(mxml_node_t *node, void *p,
126 mxml_save_cb_t cb, int col,
127 _mxml_putc_cb_t putc_cb,
128 _mxml_global_t *global);
129static int mxml_write_string(const char *s, void *p,
130 _mxml_putc_cb_t putc_cb);
131static int mxml_write_ws(mxml_node_t *node, void *p,
132 mxml_save_cb_t cb, int ws,
133 int col, _mxml_putc_cb_t putc_cb);
134
135
136/*
137 * 'mxmlLoadFd()' - Load a file descriptor into an XML node tree.
138 *
139 * The nodes in the specified file are added to the specified top node.
140 * If no top node is provided, the XML file MUST be well-formed with a
141 * single parent node like <?xml> for the entire file. The callback
142 * function returns the value type that should be used for child nodes.
143 * If MXML_NO_CALLBACK is specified then all child nodes will be either
144 * MXML_ELEMENT or MXML_TEXT nodes.
145 *
146 * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
147 * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
148 * child nodes of the specified type.
149 */
150
151mxml_node_t * /* O - First node or NULL if the file could not be read. */
152mxmlLoadFd(mxml_node_t *top, /* I - Top node */
153 int fd, /* I - File descriptor to read from */
154 mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */
155{
156 _mxml_fdbuf_t buf; /* File descriptor buffer */
157
158
159 /*
160 * Initialize the file descriptor buffer...
161 */
162
163 buf.fd = fd;
164 buf.current = buf.buffer;
165 buf.end = buf.buffer;
166
167 /*
168 * Read the XML data...
169 */
170
171 return (mxml_load_data(top, &buf, cb, mxml_fd_getc, MXML_NO_CALLBACK, NULL));
172}
173
174
175/*
176 * 'mxmlLoadFile()' - Load a file into an XML node tree.
177 *
178 * The nodes in the specified file are added to the specified top node.
179 * If no top node is provided, the XML file MUST be well-formed with a
180 * single parent node like <?xml> for the entire file. The callback
181 * function returns the value type that should be used for child nodes.
182 * If MXML_NO_CALLBACK is specified then all child nodes will be either
183 * MXML_ELEMENT or MXML_TEXT nodes.
184 *
185 * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
186 * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
187 * child nodes of the specified type.
188 */
189
190mxml_node_t * /* O - First node or NULL if the file could not be read. */
191mxmlLoadFile(mxml_node_t *top, /* I - Top node */
192 FILE *fp, /* I - File to read from */
193 mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */
194{
195 /*
196 * Read the XML data...
197 */
198
199 return (mxml_load_data(top, fp, cb, mxml_file_getc, MXML_NO_CALLBACK, NULL));
200}
201
202
203/*
204 * 'mxmlLoadString()' - Load a string into an XML node tree.
205 *
206 * The nodes in the specified string are added to the specified top node.
207 * If no top node is provided, the XML string MUST be well-formed with a
208 * single parent node like <?xml> for the entire string. The callback
209 * function returns the value type that should be used for child nodes.
210 * If MXML_NO_CALLBACK is specified then all child nodes will be either
211 * MXML_ELEMENT or MXML_TEXT nodes.
212 *
213 * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
214 * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
215 * child nodes of the specified type.
216 */
217
218mxml_node_t * /* O - First node or NULL if the string has errors. */
219mxmlLoadString(mxml_node_t *top, /* I - Top node */
220 const char *s, /* I - String to load */
221 mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */
222{
223 /*
224 * Read the XML data...
225 */
226
227 return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, MXML_NO_CALLBACK,
228 NULL));
229}
230
231
232/*
233 * 'mxmlSaveAllocString()' - Save an XML tree to an allocated string.
234 *
235 * This function returns a pointer to a string containing the textual
236 * representation of the XML node tree. The string should be freed
237 * using the free() function when you are done with it. NULL is returned
238 * if the node would produce an empty string or if the string cannot be
239 * allocated.
240 *
241 * The callback argument specifies a function that returns a whitespace
242 * string or NULL before and after each element. If MXML_NO_CALLBACK
243 * is specified, whitespace will only be added before MXML_TEXT nodes
244 * with leading whitespace and before attribute names inside opening
245 * element tags.
246 */
247
248char * /* O - Allocated string or NULL */
249mxmlSaveAllocString(
250 mxml_node_t *node, /* I - Node to write */
251 mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
252{
253 int bytes; /* Required bytes */
254 char buffer[8192]; /* Temporary buffer */
255 char *s; /* Allocated string */
256
257
258 /*
259 * Write the node to the temporary buffer...
260 */
261
262 bytes = mxmlSaveString(node, buffer, sizeof(buffer), cb);
263
264 if (bytes <= 0)
265 return (NULL);
266
267 if (bytes < (int)(sizeof(buffer) - 1))
268 {
269 /*
270 * Node fit inside the buffer, so just duplicate that string and
271 * return...
272 */
273
274 return (strdup(buffer));
275 }
276
277 /*
278 * Allocate a buffer of the required size and save the node to the
279 * new buffer...
280 */
281
282 if ((s = malloc(bytes + 1)) == NULL)
283 return (NULL);
284
285 mxmlSaveString(node, s, bytes + 1, cb);
286
287 /*
288 * Return the allocated string...
289 */
290
291 return (s);
292}
293
294
295/*
296 * 'mxmlSaveFd()' - Save an XML tree to a file descriptor.
297 *
298 * The callback argument specifies a function that returns a whitespace
299 * string or NULL before and after each element. If MXML_NO_CALLBACK
300 * is specified, whitespace will only be added before MXML_TEXT nodes
301 * with leading whitespace and before attribute names inside opening
302 * element tags.
303 */
304
305int /* O - 0 on success, -1 on error. */
306mxmlSaveFd(mxml_node_t *node, /* I - Node to write */
307 int fd, /* I - File descriptor to write to */
308 mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
309{
310 int col; /* Final column */
311 _mxml_fdbuf_t buf; /* File descriptor buffer */
312 _mxml_global_t *global = _mxml_global();
313 /* Global data */
314
315
316 /*
317 * Initialize the file descriptor buffer...
318 */
319
320 buf.fd = fd;
321 buf.current = buf.buffer;
322 buf.end = buf.buffer + sizeof(buf.buffer);
323
324 /*
325 * Write the node...
326 */
327
328 if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc, global)) < 0)
329 return (-1);
330
331 if (col > 0)
332 if (mxml_fd_putc('\n', &buf) < 0)
333 return (-1);
334
335 /*
336 * Flush and return...
337 */
338
339 return (mxml_fd_write(&buf));
340}
341
342
343/*
344 * 'mxmlSaveFile()' - Save an XML tree to a file.
345 *
346 * The callback argument specifies a function that returns a whitespace
347 * string or NULL before and after each element. If MXML_NO_CALLBACK
348 * is specified, whitespace will only be added before MXML_TEXT nodes
349 * with leading whitespace and before attribute names inside opening
350 * element tags.
351 */
352
353int /* O - 0 on success, -1 on error. */
354mxmlSaveFile(mxml_node_t *node, /* I - Node to write */
355 FILE *fp, /* I - File to write to */
356 mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
357{
358 int col; /* Final column */
359 _mxml_global_t *global = _mxml_global();
360 /* Global data */
361
362
363 /*
364 * Write the node...
365 */
366
367 if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc, global)) < 0)
368 return (-1);
369
370 if (col > 0)
371 if (putc('\n', fp) < 0)
372 return (-1);
373
374 /*
375 * Return 0 (success)...
376 */
377
378 return (0);
379}
380
381
382/*
383 * 'mxmlSaveString()' - Save an XML node tree to a string.
384 *
385 * This function returns the total number of bytes that would be
386 * required for the string but only copies (bufsize - 1) characters
387 * into the specified buffer.
388 *
389 * The callback argument specifies a function that returns a whitespace
390 * string or NULL before and after each element. If MXML_NO_CALLBACK
391 * is specified, whitespace will only be added before MXML_TEXT nodes
392 * with leading whitespace and before attribute names inside opening
393 * element tags.
394 */
395
396int /* O - Size of string */
397mxmlSaveString(mxml_node_t *node, /* I - Node to write */
398 char *buffer, /* I - String buffer */
399 int bufsize, /* I - Size of string buffer */
400 mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
401{
402 int col; /* Final column */
403 char *ptr[2]; /* Pointers for putc_cb */
404 _mxml_global_t *global = _mxml_global();
405 /* Global data */
406
407
408 /*
409 * Write the node...
410 */
411
412 ptr[0] = buffer;
413 ptr[1] = buffer + bufsize;
414
415 if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global)) < 0)
416 return (-1);
417
418 if (col > 0)
419 mxml_string_putc('\n', ptr);
420
421 /*
422 * Nul-terminate the buffer...
423 */
424
425 if (ptr[0] >= ptr[1])
426 buffer[bufsize - 1] = '\0';
427 else
428 ptr[0][0] = '\0';
429
430 /*
431 * Return the number of characters...
432 */
433
434 return (ptr[0] - buffer);
435}
436
437
438/*
439 * 'mxmlSAXLoadFd()' - Load a file descriptor into an XML node tree
440 * using a SAX callback.
441 *
442 * The nodes in the specified file are added to the specified top node.
443 * If no top node is provided, the XML file MUST be well-formed with a
444 * single parent node like <?xml> for the entire file. The callback
445 * function returns the value type that should be used for child nodes.
446 * If MXML_NO_CALLBACK is specified then all child nodes will be either
447 * MXML_ELEMENT or MXML_TEXT nodes.
448 *
449 * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
450 * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
451 * child nodes of the specified type.
452 *
453 * The SAX callback must call mxmlRetain() for any nodes that need to
454 * be kept for later use. Otherwise, nodes are deleted when the parent
455 * node is closed or after each data, comment, CDATA, or directive node.
456 *
457 * @since Mini-XML 2.3@
458 */
459
460mxml_node_t * /* O - First node or NULL if the file could not be read. */
461mxmlSAXLoadFd(mxml_node_t *top, /* I - Top node */
462 int fd, /* I - File descriptor to read from */
463 mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
464 mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
465 void *sax_data) /* I - SAX user data */
466{
467 _mxml_fdbuf_t buf; /* File descriptor buffer */
468
469
470 /*
471 * Initialize the file descriptor buffer...
472 */
473
474 buf.fd = fd;
475 buf.current = buf.buffer;
476 buf.end = buf.buffer;
477
478 /*
479 * Read the XML data...
480 */
481
482 return (mxml_load_data(top, &buf, cb, mxml_fd_getc, sax_cb, sax_data));
483}
484
485
486/*
487 * 'mxmlSAXLoadFile()' - Load a file into an XML node tree
488 * using a SAX callback.
489 *
490 * The nodes in the specified file are added to the specified top node.
491 * If no top node is provided, the XML file MUST be well-formed with a
492 * single parent node like <?xml> for the entire file. The callback
493 * function returns the value type that should be used for child nodes.
494 * If MXML_NO_CALLBACK is specified then all child nodes will be either
495 * MXML_ELEMENT or MXML_TEXT nodes.
496 *
497 * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
498 * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
499 * child nodes of the specified type.
500 *
501 * The SAX callback must call mxmlRetain() for any nodes that need to
502 * be kept for later use. Otherwise, nodes are deleted when the parent
503 * node is closed or after each data, comment, CDATA, or directive node.
504 *
505 * @since Mini-XML 2.3@
506 */
507
508mxml_node_t * /* O - First node or NULL if the file could not be read. */
509mxmlSAXLoadFile(
510 mxml_node_t *top, /* I - Top node */
511 FILE *fp, /* I - File to read from */
512 mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
513 mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
514 void *sax_data) /* I - SAX user data */
515{
516 /*
517 * Read the XML data...
518 */
519
520 return (mxml_load_data(top, fp, cb, mxml_file_getc, sax_cb, sax_data));
521}
522
523
524/*
525 * 'mxmlSAXLoadString()' - Load a string into an XML node tree
526 * using a SAX callback.
527 *
528 * The nodes in the specified string are added to the specified top node.
529 * If no top node is provided, the XML string MUST be well-formed with a
530 * single parent node like <?xml> for the entire string. The callback
531 * function returns the value type that should be used for child nodes.
532 * If MXML_NO_CALLBACK is specified then all child nodes will be either
533 * MXML_ELEMENT or MXML_TEXT nodes.
534 *
535 * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
536 * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
537 * child nodes of the specified type.
538 *
539 * The SAX callback must call mxmlRetain() for any nodes that need to
540 * be kept for later use. Otherwise, nodes are deleted when the parent
541 * node is closed or after each data, comment, CDATA, or directive node.
542 *
543 * @since Mini-XML 2.3@
544 */
545
546mxml_node_t * /* O - First node or NULL if the string has errors. */
547mxmlSAXLoadString(
548 mxml_node_t *top, /* I - Top node */
549 const char *s, /* I - String to load */
550 mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
551 mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
552 void *sax_data) /* I - SAX user data */
553{
554 /*
555 * Read the XML data...
556 */
557
558 return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, sax_cb, sax_data));
559}
560
561
562/*
563 * 'mxmlSetCustomHandlers()' - Set the handling functions for custom data.
564 *
565 * The load function accepts a node pointer and a data string and must
566 * return 0 on success and non-zero on error.
567 *
568 * The save function accepts a node pointer and must return a malloc'd
569 * string on success and NULL on error.
570 *
571 */
572
573void
574mxmlSetCustomHandlers(
575 mxml_custom_load_cb_t load, /* I - Load function */
576 mxml_custom_save_cb_t save) /* I - Save function */
577{
578 _mxml_global_t *global = _mxml_global();
579 /* Global data */
580
581
582 global->custom_load_cb = load;
583 global->custom_save_cb = save;
584}
585
586
587/*
588 * 'mxmlSetErrorCallback()' - Set the error message callback.
589 */
590
591void
592mxmlSetErrorCallback(mxml_error_cb_t cb)/* I - Error callback function */
593{
594 _mxml_global_t *global = _mxml_global();
595 /* Global data */
596
597
598 global->error_cb = cb;
599}
600
601
602/*
603 * 'mxmlSetWrapMargin()' - Set the wrap margin when saving XML data.
604 *
605 * Wrapping is disabled when "column" is 0.
606 *
607 * @since Mini-XML 2.3@
608 */
609
610void
611mxmlSetWrapMargin(int column) /* I - Column for wrapping, 0 to disable wrapping */
612{
613 _mxml_global_t *global = _mxml_global();
614 /* Global data */
615
616
617 global->wrap = column;
618}
619
620
621/*
622 * 'mxml_add_char()' - Add a character to a buffer, expanding as needed.
623 */
624
625static int /* O - 0 on success, -1 on error */
626mxml_add_char(int ch, /* I - Character to add */
627 char **bufptr, /* IO - Current position in buffer */
628 char **buffer, /* IO - Current buffer */
629 int *bufsize) /* IO - Current buffer size */
630{
631 char *newbuffer; /* New buffer value */
632
633
634 if (*bufptr >= (*buffer + *bufsize - 4))
635 {
636 /*
637 * Increase the size of the buffer...
638 */
639
640 if (*bufsize < 1024)
641 (*bufsize) *= 2;
642 else
643 (*bufsize) += 1024;
644
645 if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
646 {
647 free(*buffer);
648
649 mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
650
651 return (-1);
652 }
653
654 *bufptr = newbuffer + (*bufptr - *buffer);
655 *buffer = newbuffer;
656 }
657
658 if (ch < 0x80)
659 {
660 /*
661 * Single byte ASCII...
662 */
663
664 *(*bufptr)++ = ch;
665 }
666 else if (ch < 0x800)
667 {
668 /*
669 * Two-byte UTF-8...
670 */
671
672 *(*bufptr)++ = 0xc0 | (ch >> 6);
673 *(*bufptr)++ = 0x80 | (ch & 0x3f);
674 }
675 else if (ch < 0x10000)
676 {
677 /*
678 * Three-byte UTF-8...
679 */
680
681 *(*bufptr)++ = 0xe0 | (ch >> 12);
682 *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
683 *(*bufptr)++ = 0x80 | (ch & 0x3f);
684 }
685 else
686 {
687 /*
688 * Four-byte UTF-8...
689 */
690
691 *(*bufptr)++ = 0xf0 | (ch >> 18);
692 *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
693 *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
694 *(*bufptr)++ = 0x80 | (ch & 0x3f);
695 }
696
697 return (0);
698}
699
700
701/*
702 * 'mxml_fd_getc()' - Read a character from a file descriptor.
703 */
704
705static int /* O - Character or EOF */
706mxml_fd_getc(void *p, /* I - File descriptor buffer */
707 int *encoding) /* IO - Encoding */
708{
709 _mxml_fdbuf_t *buf; /* File descriptor buffer */
710 int ch, /* Current character */
711 temp; /* Temporary character */
712
713
714 /*
715 * Grab the next character in the buffer...
716 */
717
718 buf = (_mxml_fdbuf_t *)p;
719
720 if (buf->current >= buf->end)
721 if (mxml_fd_read(buf) < 0)
722 return (EOF);
723
724 ch = *(buf->current)++;
725
726 switch (*encoding)
727 {
728 case ENCODE_UTF8 :
729 /*
730 * Got a UTF-8 character; convert UTF-8 to Unicode and return...
731 */
732
733 if (!(ch & 0x80))
734 {
735#if DEBUG > 1
736 printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
737#endif /* DEBUG > 1 */
738
739 if (mxml_bad_char(ch))
740 {
741 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
742 ch);
743 return (EOF);
744 }
745
746 return (ch);
747 }
748 else if (ch == 0xfe)
749 {
750 /*
751 * UTF-16 big-endian BOM?
752 */
753
754 if (buf->current >= buf->end)
755 if (mxml_fd_read(buf) < 0)
756 return (EOF);
757
758 ch = *(buf->current)++;
759
760 if (ch != 0xff)
761 return (EOF);
762
763 *encoding = ENCODE_UTF16BE;
764
765 return (mxml_fd_getc(p, encoding));
766 }
767 else if (ch == 0xff)
768 {
769 /*
770 * UTF-16 little-endian BOM?
771 */
772
773 if (buf->current >= buf->end)
774 if (mxml_fd_read(buf) < 0)
775 return (EOF);
776
777 ch = *(buf->current)++;
778
779 if (ch != 0xfe)
780 return (EOF);
781
782 *encoding = ENCODE_UTF16LE;
783
784 return (mxml_fd_getc(p, encoding));
785 }
786 else if ((ch & 0xe0) == 0xc0)
787 {
788 /*
789 * Two-byte value...
790 */
791
792 if (buf->current >= buf->end)
793 if (mxml_fd_read(buf) < 0)
794 return (EOF);
795
796 temp = *(buf->current)++;
797
798 if ((temp & 0xc0) != 0x80)
799 return (EOF);
800
801 ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
802
803 if (ch < 0x80)
804 {
805 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
806 return (EOF);
807 }
808 }
809 else if ((ch & 0xf0) == 0xe0)
810 {
811 /*
812 * Three-byte value...
813 */
814
815 if (buf->current >= buf->end)
816 if (mxml_fd_read(buf) < 0)
817 return (EOF);
818
819 temp = *(buf->current)++;
820
821 if ((temp & 0xc0) != 0x80)
822 return (EOF);
823
824 ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
825
826 if (buf->current >= buf->end)
827 if (mxml_fd_read(buf) < 0)
828 return (EOF);
829
830 temp = *(buf->current)++;
831
832 if ((temp & 0xc0) != 0x80)
833 return (EOF);
834
835 ch = (ch << 6) | (temp & 0x3f);
836
837 if (ch < 0x800)
838 {
839 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
840 return (EOF);
841 }
842
843 /*
844 * Ignore (strip) Byte Order Mark (BOM)...
845 */
846
847 if (ch == 0xfeff)
848 return (mxml_fd_getc(p, encoding));
849 }
850 else if ((ch & 0xf8) == 0xf0)
851 {
852 /*
853 * Four-byte value...
854 */
855
856 if (buf->current >= buf->end)
857 if (mxml_fd_read(buf) < 0)
858 return (EOF);
859
860 temp = *(buf->current)++;
861
862 if ((temp & 0xc0) != 0x80)
863 return (EOF);
864
865 ch = ((ch & 0x07) << 6) | (temp & 0x3f);
866
867 if (buf->current >= buf->end)
868 if (mxml_fd_read(buf) < 0)
869 return (EOF);
870
871 temp = *(buf->current)++;
872
873 if ((temp & 0xc0) != 0x80)
874 return (EOF);
875
876 ch = (ch << 6) | (temp & 0x3f);
877
878 if (buf->current >= buf->end)
879 if (mxml_fd_read(buf) < 0)
880 return (EOF);
881
882 temp = *(buf->current)++;
883
884 if ((temp & 0xc0) != 0x80)
885 return (EOF);
886
887 ch = (ch << 6) | (temp & 0x3f);
888
889 if (ch < 0x10000)
890 {
891 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
892 return (EOF);
893 }
894 }
895 else
896 return (EOF);
897 break;
898
899 case ENCODE_UTF16BE :
900 /*
901 * Read UTF-16 big-endian char...
902 */
903
904 if (buf->current >= buf->end)
905 if (mxml_fd_read(buf) < 0)
906 return (EOF);
907
908 temp = *(buf->current)++;
909
910 ch = (ch << 8) | temp;
911
912 if (mxml_bad_char(ch))
913 {
914 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
915 ch);
916 return (EOF);
917 }
918 else if (ch >= 0xd800 && ch <= 0xdbff)
919 {
920 /*
921 * Multi-word UTF-16 char...
922 */
923
924 int lch;
925
926 if (buf->current >= buf->end)
927 if (mxml_fd_read(buf) < 0)
928 return (EOF);
929
930 lch = *(buf->current)++;
931
932 if (buf->current >= buf->end)
933 if (mxml_fd_read(buf) < 0)
934 return (EOF);
935
936 temp = *(buf->current)++;
937
938 lch = (lch << 8) | temp;
939
940 if (lch < 0xdc00 || lch >= 0xdfff)
941 return (EOF);
942
943 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
944 }
945 break;
946
947 case ENCODE_UTF16LE :
948 /*
949 * Read UTF-16 little-endian char...
950 */
951
952 if (buf->current >= buf->end)
953 if (mxml_fd_read(buf) < 0)
954 return (EOF);
955
956 temp = *(buf->current)++;
957
958 ch |= (temp << 8);
959
960 if (mxml_bad_char(ch))
961 {
962 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
963 ch);
964 return (EOF);
965 }
966 else if (ch >= 0xd800 && ch <= 0xdbff)
967 {
968 /*
969 * Multi-word UTF-16 char...
970 */
971
972 int lch;
973
974 if (buf->current >= buf->end)
975 if (mxml_fd_read(buf) < 0)
976 return (EOF);
977
978 lch = *(buf->current)++;
979
980 if (buf->current >= buf->end)
981 if (mxml_fd_read(buf) < 0)
982 return (EOF);
983
984 temp = *(buf->current)++;
985
986 lch |= (temp << 8);
987
988 if (lch < 0xdc00 || lch >= 0xdfff)
989 return (EOF);
990
991 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
992 }
993 break;
994 }
995
996#if DEBUG > 1
997 printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
998#endif /* DEBUG > 1 */
999
1000 return (ch);
1001}
1002
1003
1004/*
1005 * 'mxml_fd_putc()' - Write a character to a file descriptor.
1006 */
1007
1008static int /* O - 0 on success, -1 on error */
1009mxml_fd_putc(int ch, /* I - Character */
1010 void *p) /* I - File descriptor buffer */
1011{
1012 _mxml_fdbuf_t *buf; /* File descriptor buffer */
1013
1014
1015 /*
1016 * Flush the write buffer as needed...
1017 */
1018
1019 buf = (_mxml_fdbuf_t *)p;
1020
1021 if (buf->current >= buf->end)
1022 if (mxml_fd_write(buf) < 0)
1023 return (-1);
1024
1025 *(buf->current)++ = ch;
1026
1027 /*
1028 * Return successfully...
1029 */
1030
1031 return (0);
1032}
1033
1034
1035/*
1036 * 'mxml_fd_read()' - Read a buffer of data from a file descriptor.
1037 */
1038
1039static int /* O - 0 on success, -1 on error */
1040mxml_fd_read(_mxml_fdbuf_t *buf) /* I - File descriptor buffer */
1041{
1042 int bytes; /* Bytes read... */
1043
1044
1045 /*
1046 * Range check input...
1047 */
1048
1049 if (!buf)
1050 return (-1);
1051
1052 /*
1053 * Read from the file descriptor...
1054 */
1055
1056 while ((bytes = read(buf->fd, buf->buffer, sizeof(buf->buffer))) < 0)
1057#ifdef EINTR
1058 if (errno != EAGAIN && errno != EINTR)
1059#else
1060 if (errno != EAGAIN)
1061#endif /* EINTR */
1062 return (-1);
1063
1064 if (bytes == 0)
1065 return (-1);
1066
1067 /*
1068 * Update the pointers and return success...
1069 */
1070
1071 buf->current = buf->buffer;
1072 buf->end = buf->buffer + bytes;
1073
1074 return (0);
1075}
1076
1077
1078/*
1079 * 'mxml_fd_write()' - Write a buffer of data to a file descriptor.
1080 */
1081
1082static int /* O - 0 on success, -1 on error */
1083mxml_fd_write(_mxml_fdbuf_t *buf) /* I - File descriptor buffer */
1084{
1085 int bytes; /* Bytes written */
1086 unsigned char *ptr; /* Pointer into buffer */
1087
1088
1089 /*
1090 * Range check...
1091 */
1092
1093 if (!buf)
1094 return (-1);
1095
1096 /*
1097 * Return 0 if there is nothing to write...
1098 */
1099
1100 if (buf->current == buf->buffer)
1101 return (0);
1102
1103 /*
1104 * Loop until we have written everything...
1105 */
1106
1107 for (ptr = buf->buffer; ptr < buf->current; ptr += bytes)
1108 if ((bytes = write(buf->fd, ptr, buf->current - ptr)) < 0)
1109 return (-1);
1110
1111 /*
1112 * All done, reset pointers and return success...
1113 */
1114
1115 buf->current = buf->buffer;
1116
1117 return (0);
1118}
1119
1120
1121/*
1122 * 'mxml_file_getc()' - Get a character from a file.
1123 */
1124
1125static int /* O - Character or EOF */
1126mxml_file_getc(void *p, /* I - Pointer to file */
1127 int *encoding) /* IO - Encoding */
1128{
1129 int ch, /* Character from file */
1130 temp; /* Temporary character */
1131 FILE *fp; /* Pointer to file */
1132
1133
1134 /*
1135 * Read a character from the file and see if it is EOF or ASCII...
1136 */
1137
1138 fp = (FILE *)p;
1139 ch = getc(fp);
1140
1141 if (ch == EOF)
1142 return (EOF);
1143
1144 switch (*encoding)
1145 {
1146 case ENCODE_UTF8 :
1147 /*
1148 * Got a UTF-8 character; convert UTF-8 to Unicode and return...
1149 */
1150
1151 if (!(ch & 0x80))
1152 {
1153 if (mxml_bad_char(ch))
1154 {
1155 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
1156 ch);
1157 return (EOF);
1158 }
1159
1160#if DEBUG > 1
1161 printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
1162#endif /* DEBUG > 1 */
1163
1164 return (ch);
1165 }
1166 else if (ch == 0xfe)
1167 {
1168 /*
1169 * UTF-16 big-endian BOM?
1170 */
1171
1172 ch = getc(fp);
1173 if (ch != 0xff)
1174 return (EOF);
1175
1176 *encoding = ENCODE_UTF16BE;
1177
1178 return (mxml_file_getc(p, encoding));
1179 }
1180 else if (ch == 0xff)
1181 {
1182 /*
1183 * UTF-16 little-endian BOM?
1184 */
1185
1186 ch = getc(fp);
1187 if (ch != 0xfe)
1188 return (EOF);
1189
1190 *encoding = ENCODE_UTF16LE;
1191
1192 return (mxml_file_getc(p, encoding));
1193 }
1194 else if ((ch & 0xe0) == 0xc0)
1195 {
1196 /*
1197 * Two-byte value...
1198 */
1199
1200 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
1201 return (EOF);
1202
1203 ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
1204
1205 if (ch < 0x80)
1206 {
1207 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
1208 return (EOF);
1209 }
1210 }
1211 else if ((ch & 0xf0) == 0xe0)
1212 {
1213 /*
1214 * Three-byte value...
1215 */
1216
1217 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
1218 return (EOF);
1219
1220 ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
1221
1222 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
1223 return (EOF);
1224
1225 ch = (ch << 6) | (temp & 0x3f);
1226
1227 if (ch < 0x800)
1228 {
1229 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
1230 return (EOF);
1231 }
1232
1233 /*
1234 * Ignore (strip) Byte Order Mark (BOM)...
1235 */
1236
1237 if (ch == 0xfeff)
1238 return (mxml_file_getc(p, encoding));
1239 }
1240 else if ((ch & 0xf8) == 0xf0)
1241 {
1242 /*
1243 * Four-byte value...
1244 */
1245
1246 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
1247 return (EOF);
1248
1249 ch = ((ch & 0x07) << 6) | (temp & 0x3f);
1250
1251 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
1252 return (EOF);
1253
1254 ch = (ch << 6) | (temp & 0x3f);
1255
1256 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
1257 return (EOF);
1258
1259 ch = (ch << 6) | (temp & 0x3f);
1260
1261 if (ch < 0x10000)
1262 {
1263 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
1264 return (EOF);
1265 }
1266 }
1267 else
1268 return (EOF);
1269 break;
1270
1271 case ENCODE_UTF16BE :
1272 /*
1273 * Read UTF-16 big-endian char...
1274 */
1275
1276 ch = (ch << 8) | getc(fp);
1277
1278 if (mxml_bad_char(ch))
1279 {
1280 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
1281 ch);
1282 return (EOF);
1283 }
1284 else if (ch >= 0xd800 && ch <= 0xdbff)
1285 {
1286 /*
1287 * Multi-word UTF-16 char...
1288 */
1289
1290 int lch = (getc(fp) << 8) | getc(fp);
1291
1292 if (lch < 0xdc00 || lch >= 0xdfff)
1293 return (EOF);
1294
1295 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
1296 }
1297 break;
1298
1299 case ENCODE_UTF16LE :
1300 /*
1301 * Read UTF-16 little-endian char...
1302 */
1303
1304 ch |= (getc(fp) << 8);
1305
1306 if (mxml_bad_char(ch))
1307 {
1308 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
1309 ch);
1310 return (EOF);
1311 }
1312 else if (ch >= 0xd800 && ch <= 0xdbff)
1313 {
1314 /*
1315 * Multi-word UTF-16 char...
1316 */
1317
1318 int lch = getc(fp) | (getc(fp) << 8);
1319
1320 if (lch < 0xdc00 || lch >= 0xdfff)
1321 return (EOF);
1322
1323 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
1324 }
1325 break;
1326 }
1327
1328#if DEBUG > 1
1329 printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
1330#endif /* DEBUG > 1 */
1331
1332 return (ch);
1333}
1334
1335
1336/*
1337 * 'mxml_file_putc()' - Write a character to a file.
1338 */
1339
1340static int /* O - 0 on success, -1 on failure */
1341mxml_file_putc(int ch, /* I - Character to write */
1342 void *p) /* I - Pointer to file */
1343{
1344 return (putc(ch, (FILE *)p) == EOF ? -1 : 0);
1345}
1346
1347
1348/*
1349 * 'mxml_get_entity()' - Get the character corresponding to an entity...
1350 */
1351
1352static int /* O - Character value or EOF on error */
1353mxml_get_entity(mxml_node_t *parent, /* I - Parent node */
1354 void *p, /* I - Pointer to source */
1355 int *encoding, /* IO - Character encoding */
1356 int (*getc_cb)(void *, int *))
1357 /* I - Get character function */
1358{
1359 int ch; /* Current character */
1360 char entity[64], /* Entity string */
1361 *entptr; /* Pointer into entity */
1362
1363
1364 entptr = entity;
1365
1366 while ((ch = (*getc_cb)(p, encoding)) != EOF)
1367 if (ch > 126 || (!isalnum(ch) && ch != '#'))
1368 break;
1369 else if (entptr < (entity + sizeof(entity) - 1))
1370 *entptr++ = ch;
1371 else
1372 {
1373 mxml_error("Entity name too long under parent <%s>!",
1374 parent ? parent->value.element.name : "null");
1375 break;
1376 }
1377
1378 *entptr = '\0';
1379
1380 if (ch != ';')
1381 {
1382 mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
1383 entity, parent ? parent->value.element.name : "null");
1384 return (EOF);
1385 }
1386
1387 if (entity[0] == '#')
1388 {
1389 if (entity[1] == 'x')
1390 ch = strtol(entity + 2, NULL, 16);
1391 else
1392 ch = strtol(entity + 1, NULL, 10);
1393 }
1394 else if ((ch = mxmlEntityGetValue(entity)) < 0)
1395 mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
1396 entity, parent ? parent->value.element.name : "null");
1397
1398 if (mxml_bad_char(ch))
1399 {
1400 mxml_error("Bad control character 0x%02x under parent <%s> not allowed by XML standard!",
1401 ch, parent ? parent->value.element.name : "null");
1402 return (EOF);
1403 }
1404
1405 return (ch);
1406}
1407
1408
1409/*
1410 * 'mxml_load_data()' - Load data into an XML node tree.
1411 */
1412
1413static mxml_node_t * /* O - First node or NULL if the file could not be read. */
1414mxml_load_data(
1415 mxml_node_t *top, /* I - Top node */
1416 void *p, /* I - Pointer to data */
1417 mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
1418 _mxml_getc_cb_t getc_cb, /* I - Read function */
1419 mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
1420 void *sax_data) /* I - SAX user data */
1421{
1422 mxml_node_t *node, /* Current node */
1423 *first, /* First node added */
1424 *parent; /* Current parent node */
1425 int ch, /* Character from file */
1426 whitespace; /* Non-zero if whitespace seen */
1427 char *buffer, /* String buffer */
1428 *bufptr; /* Pointer into buffer */
1429 int bufsize; /* Size of buffer */
1430 mxml_type_t type; /* Current node type */
1431 int encoding; /* Character encoding */
1432 _mxml_global_t *global = _mxml_global();
1433 /* Global data */
1434 static const char * const types[] = /* Type strings... */
1435 {
1436 "MXML_ELEMENT", /* XML element with attributes */
1437 "MXML_INTEGER", /* Integer value */
1438 "MXML_OPAQUE", /* Opaque string */
1439 "MXML_REAL", /* Real value */
1440 "MXML_TEXT", /* Text fragment */
1441 "MXML_CUSTOM" /* Custom data */
1442 };
1443
1444
1445 /*
1446 * Read elements and other nodes from the file...
1447 */
1448
1449 if ((buffer = malloc(64)) == NULL)
1450 {
1451 mxml_error("Unable to allocate string buffer!");
1452 return (NULL);
1453 }
1454
1455 bufsize = 64;
1456 bufptr = buffer;
1457 parent = top;
1458 first = NULL;
1459 whitespace = 0;
1460 encoding = ENCODE_UTF8;
1461
1462 if (cb && parent)
1463 type = (*cb)(parent);
1464 else
1465 type = MXML_TEXT;
1466
1467 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
1468 {
1469 if ((ch == '<' ||
1470 (mxml_isspace(ch) && type != MXML_OPAQUE && type != MXML_CUSTOM)) &&
1471 bufptr > buffer)
1472 {
1473 /*
1474 * Add a new value node...
1475 */
1476
1477 *bufptr = '\0';
1478
1479 switch (type)
1480 {
1481 case MXML_INTEGER :
1482 node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
1483 break;
1484
1485 case MXML_OPAQUE :
1486 node = mxmlNewOpaque(parent, buffer);
1487 break;
1488
1489 case MXML_REAL :
1490 node = mxmlNewReal(parent, strtod(buffer, &bufptr));
1491 break;
1492
1493 case MXML_TEXT :
1494 node = mxmlNewText(parent, whitespace, buffer);
1495 break;
1496
1497 case MXML_CUSTOM :
1498 if (global->custom_load_cb)
1499 {
1500 /*
1501 * Use the callback to fill in the custom data...
1502 */
1503
1504 node = mxmlNewCustom(parent, NULL, NULL);
1505
1506 if ((*global->custom_load_cb)(node, buffer))
1507 {
1508 mxml_error("Bad custom value '%s' in parent <%s>!",
1509 buffer, parent ? parent->value.element.name : "null");
1510 mxmlDelete(node);
1511 node = NULL;
1512 }
1513 break;
1514 }
1515
1516 default : /* Ignore... */
1517 node = NULL;
1518 break;
1519 }
1520
1521 if (*bufptr)
1522 {
1523 /*
1524 * Bad integer/real number value...
1525 */
1526
1527 mxml_error("Bad %s value '%s' in parent <%s>!",
1528 type == MXML_INTEGER ? "integer" : "real", buffer,
1529 parent ? parent->value.element.name : "null");
1530 break;
1531 }
1532
1533 bufptr = buffer;
1534 whitespace = mxml_isspace(ch) && type == MXML_TEXT;
1535
1536 if (!node && type != MXML_IGNORE)
1537 {
1538 /*
1539 * Print error and return...
1540 */
1541
1542 mxml_error("Unable to add value node of type %s to parent <%s>!",
1543 types[type], parent ? parent->value.element.name : "null");
1544 goto error;
1545 }
1546
1547 if (sax_cb)
1548 {
1549 (*sax_cb)(node, MXML_SAX_DATA, sax_data);
1550
1551 if (!mxmlRelease(node))
1552 node = NULL;
1553 }
1554
1555 if (!first && node)
1556 first = node;
1557 }
1558 else if (mxml_isspace(ch) && type == MXML_TEXT)
1559 whitespace = 1;
1560
1561 /*
1562 * Add lone whitespace node if we have an element and existing
1563 * whitespace...
1564 */
1565
1566 if (ch == '<' && whitespace && type == MXML_TEXT)
1567 {
1568 if (parent)
1569 {
1570 node = mxmlNewText(parent, whitespace, "");
1571
1572 if (sax_cb)
1573 {
1574 (*sax_cb)(node, MXML_SAX_DATA, sax_data);
1575
1576 if (!mxmlRelease(node))
1577 node = NULL;
1578 }
1579
1580 if (!first && node)
1581 first = node;
1582 }
1583
1584 whitespace = 0;
1585 }
1586
1587 if (ch == '<')
1588 {
1589 /*
1590 * Start of open/close tag...
1591 */
1592
1593 bufptr = buffer;
1594
1595 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
1596 if (mxml_isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
1597 break;
1598 else if (ch == '<')
1599 {
1600 mxml_error("Bare < in element!");
1601 goto error;
1602 }
1603 else if (ch == '&')
1604 {
1605 if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
1606 goto error;
1607
1608 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
1609 goto error;
1610 }
1611 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
1612 goto error;
1613 else if (((bufptr - buffer) == 1 && buffer[0] == '?') ||
1614 ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) ||
1615 ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8)))
1616 break;
1617
1618 *bufptr = '\0';
1619
1620 if (!strcmp(buffer, "!--"))
1621 {
1622 /*
1623 * Gather rest of comment...
1624 */
1625
1626 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
1627 {
1628 if (ch == '>' && bufptr > (buffer + 4) &&
1629 bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-')
1630 break;
1631 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
1632 goto error;
1633 }
1634
1635 /*
1636 * Error out if we didn't get the whole comment...
1637 */
1638
1639 if (ch != '>')
1640 {
1641 /*
1642 * Print error and return...
1643 */
1644
1645 mxml_error("Early EOF in comment node!");
1646 goto error;
1647 }
1648
1649
1650 /*
1651 * Otherwise add this as an element under the current parent...
1652 */
1653
1654 *bufptr = '\0';
1655
1656 if (!parent && first)
1657 {
1658 /*
1659 * There can only be one root element!
1660 */
1661
1662 mxml_error("<%s> cannot be a second root node after <%s>",
1663 buffer, first->value.element.name);
1664 goto error;
1665 }
1666
1667 if ((node = mxmlNewElement(parent, buffer)) == NULL)
1668 {
1669 /*
1670 * Just print error for now...
1671 */
1672
1673 mxml_error("Unable to add comment node to parent <%s>!",
1674 parent ? parent->value.element.name : "null");
1675 break;
1676 }
1677
1678 if (sax_cb)
1679 {
1680 (*sax_cb)(node, MXML_SAX_COMMENT, sax_data);
1681
1682 if (!mxmlRelease(node))
1683 node = NULL;
1684 }
1685
1686 if (node && !first)
1687 first = node;
1688 }
1689 else if (!strcmp(buffer, "![CDATA["))
1690 {
1691 /*
1692 * Gather CDATA section...
1693 */
1694
1695 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
1696 {
1697 if (ch == '>' && !strncmp(bufptr - 2, "]]", 2))
1698 break;
1699 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
1700 goto error;
1701 }
1702
1703 /*
1704 * Error out if we didn't get the whole comment...
1705 */
1706
1707 if (ch != '>')
1708 {
1709 /*
1710 * Print error and return...
1711 */
1712
1713 mxml_error("Early EOF in CDATA node!");
1714 goto error;
1715 }
1716
1717
1718 /*
1719 * Otherwise add this as an element under the current parent...
1720 */
1721
1722 *bufptr = '\0';
1723
1724 if (!parent && first)
1725 {
1726 /*
1727 * There can only be one root element!
1728 */
1729
1730 mxml_error("<%s> cannot be a second root node after <%s>",
1731 buffer, first->value.element.name);
1732 goto error;
1733 }
1734
1735 if ((node = mxmlNewElement(parent, buffer)) == NULL)
1736 {
1737 /*
1738 * Print error and return...
1739 */
1740
1741 mxml_error("Unable to add CDATA node to parent <%s>!",
1742 parent ? parent->value.element.name : "null");
1743 goto error;
1744 }
1745
1746 if (sax_cb)
1747 {
1748 (*sax_cb)(node, MXML_SAX_CDATA, sax_data);
1749
1750 if (!mxmlRelease(node))
1751 node = NULL;
1752 }
1753
1754 if (node && !first)
1755 first = node;
1756 }
1757 else if (buffer[0] == '?')
1758 {
1759 /*
1760 * Gather rest of processing instruction...
1761 */
1762
1763 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
1764 {
1765 if (ch == '>' && bufptr > buffer && bufptr[-1] == '?')
1766 break;
1767 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
1768 goto error;
1769 }
1770
1771 /*
1772 * Error out if we didn't get the whole processing instruction...
1773 */
1774
1775 if (ch != '>')
1776 {
1777 /*
1778 * Print error and return...
1779 */
1780
1781 mxml_error("Early EOF in processing instruction node!");
1782 goto error;
1783 }
1784
1785 /*
1786 * Otherwise add this as an element under the current parent...
1787 */
1788
1789 *bufptr = '\0';
1790
1791 if (!parent && first)
1792 {
1793 /*
1794 * There can only be one root element!
1795 */
1796
1797 mxml_error("<%s> cannot be a second root node after <%s>",
1798 buffer, first->value.element.name);
1799 goto error;
1800 }
1801
1802 if ((node = mxmlNewElement(parent, buffer)) == NULL)
1803 {
1804 /*
1805 * Print error and return...
1806 */
1807
1808 mxml_error("Unable to add processing instruction node to parent <%s>!",
1809 parent ? parent->value.element.name : "null");
1810 goto error;
1811 }
1812
1813 if (sax_cb)
1814 {
1815 (*sax_cb)(node, MXML_SAX_DIRECTIVE, sax_data);
1816
1817 if (!mxmlRelease(node))
1818 node = NULL;
1819 }
1820
1821 if (node)
1822 {
1823 if (!first)
1824 first = node;
1825
1826 if (!parent)
1827 {
1828 parent = node;
1829
1830 if (cb)
1831 type = (*cb)(parent);
1832 }
1833 }
1834 }
1835 else if (buffer[0] == '!')
1836 {
1837 /*
1838 * Gather rest of declaration...
1839 */
1840
1841 do
1842 {
1843 if (ch == '>')
1844 break;
1845 else
1846 {
1847 if (ch == '&')
1848 if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
1849 goto error;
1850
1851 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
1852 goto error;
1853 }
1854 }
1855 while ((ch = (*getc_cb)(p, &encoding)) != EOF);
1856
1857 /*
1858 * Error out if we didn't get the whole declaration...
1859 */
1860
1861 if (ch != '>')
1862 {
1863 /*
1864 * Print error and return...
1865 */
1866
1867 mxml_error("Early EOF in declaration node!");
1868 goto error;
1869 }
1870
1871 /*
1872 * Otherwise add this as an element under the current parent...
1873 */
1874
1875 *bufptr = '\0';
1876
1877 if (!parent && first)
1878 {
1879 /*
1880 * There can only be one root element!
1881 */
1882
1883 mxml_error("<%s> cannot be a second root node after <%s>",
1884 buffer, first->value.element.name);
1885 goto error;
1886 }
1887
1888 if ((node = mxmlNewElement(parent, buffer)) == NULL)
1889 {
1890 /*
1891 * Print error and return...
1892 */
1893
1894 mxml_error("Unable to add declaration node to parent <%s>!",
1895 parent ? parent->value.element.name : "null");
1896 goto error;
1897 }
1898
1899 if (sax_cb)
1900 {
1901 (*sax_cb)(node, MXML_SAX_DIRECTIVE, sax_data);
1902
1903 if (!mxmlRelease(node))
1904 node = NULL;
1905 }
1906
1907 if (node)
1908 {
1909 if (!first)
1910 first = node;
1911
1912 if (!parent)
1913 {
1914 parent = node;
1915
1916 if (cb)
1917 type = (*cb)(parent);
1918 }
1919 }
1920 }
1921 else if (buffer[0] == '/')
1922 {
1923 /*
1924 * Handle close tag...
1925 */
1926
1927 if (!parent || strcmp(buffer + 1, parent->value.element.name))
1928 {
1929 /*
1930 * Close tag doesn't match tree; print an error for now...
1931 */
1932
1933 mxml_error("Mismatched close tag <%s> under parent <%s>!",
1934 buffer, parent ? parent->value.element.name : "(null)");
1935 goto error;
1936 }
1937
1938 /*
1939 * Keep reading until we see >...
1940 */
1941
1942 while (ch != '>' && ch != EOF)
1943 ch = (*getc_cb)(p, &encoding);
1944
1945 node = parent;
1946 parent = parent->parent;
1947
1948 if (sax_cb)
1949 {
1950 (*sax_cb)(node, MXML_SAX_ELEMENT_CLOSE, sax_data);
1951
1952 if (!mxmlRelease(node) && first == node)
1953 first = NULL;
1954 }
1955
1956 /*
1957 * Ascend into the parent and set the value type as needed...
1958 */
1959
1960 if (cb && parent)
1961 type = (*cb)(parent);
1962 }
1963 else
1964 {
1965 /*
1966 * Handle open tag...
1967 */
1968
1969 if (!parent && first)
1970 {
1971 /*
1972 * There can only be one root element!
1973 */
1974
1975 mxml_error("<%s> cannot be a second root node after <%s>",
1976 buffer, first->value.element.name);
1977 goto error;
1978 }
1979
1980 if ((node = mxmlNewElement(parent, buffer)) == NULL)
1981 {
1982 /*
1983 * Just print error for now...
1984 */
1985
1986 mxml_error("Unable to add element node to parent <%s>!",
1987 parent ? parent->value.element.name : "null");
1988 goto error;
1989 }
1990
1991 if (mxml_isspace(ch))
1992 {
1993 if ((ch = mxml_parse_element(node, p, &encoding, getc_cb)) == EOF)
1994 goto error;
1995 }
1996 else if (ch == '/')
1997 {
1998 if ((ch = (*getc_cb)(p, &encoding)) != '>')
1999 {
2000 mxml_error("Expected > but got '%c' instead for element <%s/>!",
2001 ch, buffer);
2002 mxmlDelete(node);
2003 goto error;
2004 }
2005
2006 ch = '/';
2007 }
2008
2009 if (sax_cb)
2010 (*sax_cb)(node, MXML_SAX_ELEMENT_OPEN, sax_data);
2011
2012 if (!first)
2013 first = node;
2014
2015 if (ch == EOF)
2016 break;
2017
2018 if (ch != '/')
2019 {
2020 /*
2021 * Descend into this node, setting the value type as needed...
2022 */
2023
2024 parent = node;
2025
2026 if (cb && parent)
2027 type = (*cb)(parent);
2028 }
2029 else if (sax_cb)
2030 {
2031 (*sax_cb)(node, MXML_SAX_ELEMENT_CLOSE, sax_data);
2032
2033 if (!mxmlRelease(node) && first == node)
2034 first = NULL;
2035 }
2036 }
2037
2038 bufptr = buffer;
2039 }
2040 else if (ch == '&')
2041 {
2042 /*
2043 * Add character entity to current buffer...
2044 */
2045
2046 if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
2047 goto error;
2048
2049 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
2050 goto error;
2051 }
2052 else if (type == MXML_OPAQUE || type == MXML_CUSTOM || !mxml_isspace(ch))
2053 {
2054 /*
2055 * Add character to current buffer...
2056 */
2057
2058 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
2059 goto error;
2060 }
2061 }
2062
2063 /*
2064 * Free the string buffer - we don't need it anymore...
2065 */
2066
2067 free(buffer);
2068
2069 /*
2070 * Find the top element and return it...
2071 */
2072
2073 if (parent)
2074 {
2075 node = parent;
2076
2077 while (parent->parent != top && parent->parent)
2078 parent = parent->parent;
2079
2080 if (node != parent)
2081 {
2082 mxml_error("Missing close tag </%s> under parent <%s>!",
2083 node->value.element.name,
2084 node->parent ? node->parent->value.element.name : "(null)");
2085
2086 mxmlDelete(first);
2087
2088 return (NULL);
2089 }
2090 }
2091
2092 if (parent)
2093 return (parent);
2094 else
2095 return (first);
2096
2097 /*
2098 * Common error return...
2099 */
2100
2101error:
2102
2103 mxmlDelete(first);
2104
2105 free(buffer);
2106
2107 return (NULL);
2108}
2109
2110
2111/*
2112 * 'mxml_parse_element()' - Parse an element for any attributes...
2113 */
2114
2115static int /* O - Terminating character */
2116mxml_parse_element(
2117 mxml_node_t *node, /* I - Element node */
2118 void *p, /* I - Data to read from */
2119 int *encoding, /* IO - Encoding */
2120 _mxml_getc_cb_t getc_cb) /* I - Data callback */
2121{
2122 int ch, /* Current character in file */
2123 quote; /* Quoting character */
2124 char *name, /* Attribute name */
2125 *value, /* Attribute value */
2126 *ptr; /* Pointer into name/value */
2127 int namesize, /* Size of name string */
2128 valsize; /* Size of value string */
2129
2130
2131 /*
2132 * Initialize the name and value buffers...
2133 */
2134
2135 if ((name = malloc(64)) == NULL)
2136 {
2137 mxml_error("Unable to allocate memory for name!");
2138 return (EOF);
2139 }
2140
2141 namesize = 64;
2142
2143 if ((value = malloc(64)) == NULL)
2144 {
2145 free(name);
2146 mxml_error("Unable to allocate memory for value!");
2147 return (EOF);
2148 }
2149
2150 valsize = 64;
2151
2152 /*
2153 * Loop until we hit a >, /, ?, or EOF...
2154 */
2155
2156 while ((ch = (*getc_cb)(p, encoding)) != EOF)
2157 {
2158#if DEBUG > 1
2159 fprintf(stderr, "parse_element: ch='%c'\n", ch);
2160#endif /* DEBUG > 1 */
2161
2162 /*
2163 * Skip leading whitespace...
2164 */
2165
2166 if (mxml_isspace(ch))
2167 continue;
2168
2169 /*
2170 * Stop at /, ?, or >...
2171 */
2172
2173 if (ch == '/' || ch == '?')
2174 {
2175 /*
2176 * Grab the > character and print an error if it isn't there...
2177 */
2178
2179 quote = (*getc_cb)(p, encoding);
2180
2181 if (quote != '>')
2182 {
2183 mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
2184 ch, node->value.element.name, quote);
2185 goto error;
2186 }
2187
2188 break;
2189 }
2190 else if (ch == '<')
2191 {
2192 mxml_error("Bare < in element %s!", node->value.element.name);
2193 goto error;
2194 }
2195 else if (ch == '>')
2196 break;
2197
2198 /*
2199 * Read the attribute name...
2200 */
2201
2202 name[0] = ch;
2203 ptr = name + 1;
2204
2205 if (ch == '\"' || ch == '\'')
2206 {
2207 /*
2208 * Name is in quotes, so get a quoted string...
2209 */
2210
2211 quote = ch;
2212
2213 while ((ch = (*getc_cb)(p, encoding)) != EOF)
2214 {
2215 if (ch == '&')
2216 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
2217 goto error;
2218
2219 if (mxml_add_char(ch, &ptr, &name, &namesize))
2220 goto error;
2221
2222 if (ch == quote)
2223 break;
2224 }
2225 }
2226 else
2227 {
2228 /*
2229 * Grab an normal, non-quoted name...
2230 */
2231
2232 while ((ch = (*getc_cb)(p, encoding)) != EOF)
2233 if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>' ||
2234 ch == '?')
2235 break;
2236 else
2237 {
2238 if (ch == '&')
2239 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
2240 goto error;
2241
2242 if (mxml_add_char(ch, &ptr, &name, &namesize))
2243 goto error;
2244 }
2245 }
2246
2247 *ptr = '\0';
2248
2249 if (mxmlElementGetAttr(node, name))
2250 goto error;
2251
2252 while (ch != EOF && mxml_isspace(ch))
2253 ch = (*getc_cb)(p, encoding);
2254
2255 if (ch == '=')
2256 {
2257 /*
2258 * Read the attribute value...
2259 */
2260
2261 while ((ch = (*getc_cb)(p, encoding)) != EOF && mxml_isspace(ch));
2262
2263 if (ch == EOF)
2264 {
2265 mxml_error("Missing value for attribute '%s' in element %s!",
2266 name, node->value.element.name);
2267 goto error;
2268 }
2269
2270 if (ch == '\'' || ch == '\"')
2271 {
2272 /*
2273 * Read quoted value...
2274 */
2275
2276 quote = ch;
2277 ptr = value;
2278
2279 while ((ch = (*getc_cb)(p, encoding)) != EOF)
2280 if (ch == quote)
2281 break;
2282 else
2283 {
2284 if (ch == '&')
2285 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
2286 goto error;
2287
2288 if (mxml_add_char(ch, &ptr, &value, &valsize))
2289 goto error;
2290 }
2291
2292 *ptr = '\0';
2293 }
2294 else
2295 {
2296 /*
2297 * Read unquoted value...
2298 */
2299
2300 value[0] = ch;
2301 ptr = value + 1;
2302
2303 while ((ch = (*getc_cb)(p, encoding)) != EOF)
2304 if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>')
2305 break;
2306 else
2307 {
2308 if (ch == '&')
2309 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
2310 goto error;
2311
2312 if (mxml_add_char(ch, &ptr, &value, &valsize))
2313 goto error;
2314 }
2315
2316 *ptr = '\0';
2317 }
2318
2319 /*
2320 * Set the attribute with the given string value...
2321 */
2322
2323 mxmlElementSetAttr(node, name, value);
2324 }
2325 else
2326 {
2327 mxml_error("Missing value for attribute '%s' in element %s!",
2328 name, node->value.element.name);
2329 goto error;
2330 }
2331
2332 /*
2333 * Check the end character...
2334 */
2335
2336 if (ch == '/' || ch == '?')
2337 {
2338 /*
2339 * Grab the > character and print an error if it isn't there...
2340 */
2341
2342 quote = (*getc_cb)(p, encoding);
2343
2344 if (quote != '>')
2345 {
2346 mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
2347 ch, node->value.element.name, quote);
2348 ch = EOF;
2349 }
2350
2351 break;
2352 }
2353 else if (ch == '>')
2354 break;
2355 }
2356
2357 /*
2358 * Free the name and value buffers and return...
2359 */
2360
2361 free(name);
2362 free(value);
2363
2364 return (ch);
2365
2366 /*
2367 * Common error return point...
2368 */
2369
2370error:
2371
2372 free(name);
2373 free(value);
2374
2375 return (EOF);
2376}
2377
2378
2379/*
2380 * 'mxml_string_getc()' - Get a character from a string.
2381 */
2382
2383static int /* O - Character or EOF */
2384mxml_string_getc(void *p, /* I - Pointer to file */
2385 int *encoding) /* IO - Encoding */
2386{
2387 int ch; /* Character */
2388 const char **s; /* Pointer to string pointer */
2389
2390
2391 s = (const char **)p;
2392
2393 if ((ch = (*s)[0] & 255) != 0 || *encoding == ENCODE_UTF16LE)
2394 {
2395 /*
2396 * Got character; convert UTF-8 to integer and return...
2397 */
2398
2399 (*s)++;
2400
2401 switch (*encoding)
2402 {
2403 case ENCODE_UTF8 :
2404 if (!(ch & 0x80))
2405 {
2406#if DEBUG > 1
2407 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
2408#endif /* DEBUG > 1 */
2409
2410 if (mxml_bad_char(ch))
2411 {
2412 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
2413 ch);
2414 return (EOF);
2415 }
2416
2417 return (ch);
2418 }
2419 else if (ch == 0xfe)
2420 {
2421 /*
2422 * UTF-16 big-endian BOM?
2423 */
2424
2425 if (((*s)[0] & 255) != 0xff)
2426 return (EOF);
2427
2428 *encoding = ENCODE_UTF16BE;
2429 (*s)++;
2430
2431 return (mxml_string_getc(p, encoding));
2432 }
2433 else if (ch == 0xff)
2434 {
2435 /*
2436 * UTF-16 little-endian BOM?
2437 */
2438
2439 if (((*s)[0] & 255) != 0xfe)
2440 return (EOF);
2441
2442 *encoding = ENCODE_UTF16LE;
2443 (*s)++;
2444
2445 return (mxml_string_getc(p, encoding));
2446 }
2447 else if ((ch & 0xe0) == 0xc0)
2448 {
2449 /*
2450 * Two-byte value...
2451 */
2452
2453 if (((*s)[0] & 0xc0) != 0x80)
2454 return (EOF);
2455
2456 ch = ((ch & 0x1f) << 6) | ((*s)[0] & 0x3f);
2457
2458 (*s)++;
2459
2460 if (ch < 0x80)
2461 {
2462 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
2463 return (EOF);
2464 }
2465
2466#if DEBUG > 1
2467 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
2468#endif /* DEBUG > 1 */
2469
2470 return (ch);
2471 }
2472 else if ((ch & 0xf0) == 0xe0)
2473 {
2474 /*
2475 * Three-byte value...
2476 */
2477
2478 if (((*s)[0] & 0xc0) != 0x80 ||
2479 ((*s)[1] & 0xc0) != 0x80)
2480 return (EOF);
2481
2482 ch = ((((ch & 0x0f) << 6) | ((*s)[0] & 0x3f)) << 6) | ((*s)[1] & 0x3f);
2483
2484 (*s) += 2;
2485
2486 if (ch < 0x800)
2487 {
2488 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
2489 return (EOF);
2490 }
2491
2492 /*
2493 * Ignore (strip) Byte Order Mark (BOM)...
2494 */
2495
2496 if (ch == 0xfeff)
2497 return (mxml_string_getc(p, encoding));
2498
2499#if DEBUG > 1
2500 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
2501#endif /* DEBUG > 1 */
2502
2503 return (ch);
2504 }
2505 else if ((ch & 0xf8) == 0xf0)
2506 {
2507 /*
2508 * Four-byte value...
2509 */
2510
2511 if (((*s)[0] & 0xc0) != 0x80 ||
2512 ((*s)[1] & 0xc0) != 0x80 ||
2513 ((*s)[2] & 0xc0) != 0x80)
2514 return (EOF);
2515
2516 ch = ((((((ch & 0x07) << 6) | ((*s)[0] & 0x3f)) << 6) |
2517 ((*s)[1] & 0x3f)) << 6) | ((*s)[2] & 0x3f);
2518
2519 (*s) += 3;
2520
2521 if (ch < 0x10000)
2522 {
2523 mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
2524 return (EOF);
2525 }
2526
2527#if DEBUG > 1
2528 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
2529#endif /* DEBUG > 1 */
2530
2531 return (ch);
2532 }
2533 else
2534 return (EOF);
2535
2536 case ENCODE_UTF16BE :
2537 /*
2538 * Read UTF-16 big-endian char...
2539 */
2540
2541 ch = (ch << 8) | ((*s)[0] & 255);
2542 (*s) ++;
2543
2544 if (mxml_bad_char(ch))
2545 {
2546 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
2547 ch);
2548 return (EOF);
2549 }
2550 else if (ch >= 0xd800 && ch <= 0xdbff)
2551 {
2552 /*
2553 * Multi-word UTF-16 char...
2554 */
2555
2556 int lch; /* Lower word */
2557
2558
2559 if (!(*s)[0])
2560 return (EOF);
2561
2562 lch = (((*s)[0] & 255) << 8) | ((*s)[1] & 255);
2563 (*s) += 2;
2564
2565 if (lch < 0xdc00 || lch >= 0xdfff)
2566 return (EOF);
2567
2568 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
2569 }
2570
2571#if DEBUG > 1
2572 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
2573#endif /* DEBUG > 1 */
2574
2575 return (ch);
2576
2577 case ENCODE_UTF16LE :
2578 /*
2579 * Read UTF-16 little-endian char...
2580 */
2581
2582 ch = ch | (((*s)[0] & 255) << 8);
2583
2584 if (!ch)
2585 {
2586 (*s) --;
2587 return (EOF);
2588 }
2589
2590 (*s) ++;
2591
2592 if (mxml_bad_char(ch))
2593 {
2594 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
2595 ch);
2596 return (EOF);
2597 }
2598 else if (ch >= 0xd800 && ch <= 0xdbff)
2599 {
2600 /*
2601 * Multi-word UTF-16 char...
2602 */
2603
2604 int lch; /* Lower word */
2605
2606
2607 if (!(*s)[1])
2608 return (EOF);
2609
2610 lch = (((*s)[1] & 255) << 8) | ((*s)[0] & 255);
2611 (*s) += 2;
2612
2613 if (lch < 0xdc00 || lch >= 0xdfff)
2614 return (EOF);
2615
2616 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
2617 }
2618
2619#if DEBUG > 1
2620 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
2621#endif /* DEBUG > 1 */
2622
2623 return (ch);
2624 }
2625 }
2626
2627 return (EOF);
2628}
2629
2630
2631/*
2632 * 'mxml_string_putc()' - Write a character to a string.
2633 */
2634
2635static int /* O - 0 on success, -1 on failure */
2636mxml_string_putc(int ch, /* I - Character to write */
2637 void *p) /* I - Pointer to string pointers */
2638{
2639 char **pp; /* Pointer to string pointers */
2640
2641
2642 pp = (char **)p;
2643
2644 if (pp[0] < pp[1])
2645 pp[0][0] = ch;
2646
2647 pp[0] ++;
2648
2649 return (0);
2650}
2651
2652
2653/*
2654 * 'mxml_write_name()' - Write a name string.
2655 */
2656
2657static int /* O - 0 on success, -1 on failure */
2658mxml_write_name(const char *s, /* I - Name to write */
2659 void *p, /* I - Write pointer */
2660 int (*putc_cb)(int, void *))
2661 /* I - Write callback */
2662{
2663 char quote; /* Quote character */
2664 const char *name; /* Entity name */
2665
2666
2667 if (*s == '\"' || *s == '\'')
2668 {
2669 /*
2670 * Write a quoted name string...
2671 */
2672
2673 if ((*putc_cb)(*s, p) < 0)
2674 return (-1);
2675
2676 quote = *s++;
2677
2678 while (*s && *s != quote)
2679 {
2680 if ((name = mxmlEntityGetName(*s)) != NULL)
2681 {
2682 if ((*putc_cb)('&', p) < 0)
2683 return (-1);
2684
2685 while (*name)
2686 {
2687 if ((*putc_cb)(*name, p) < 0)
2688 return (-1);
2689
2690 name ++;
2691 }
2692
2693 if ((*putc_cb)(';', p) < 0)
2694 return (-1);
2695 }
2696 else if ((*putc_cb)(*s, p) < 0)
2697 return (-1);
2698
2699 s ++;
2700 }
2701
2702 /*
2703 * Write the end quote...
2704 */
2705
2706 if ((*putc_cb)(quote, p) < 0)
2707 return (-1);
2708 }
2709 else
2710 {
2711 /*
2712 * Write a non-quoted name string...
2713 */
2714
2715 while (*s)
2716 {
2717 if ((*putc_cb)(*s, p) < 0)
2718 return (-1);
2719
2720 s ++;
2721 }
2722 }
2723
2724 return (0);
2725}
2726
2727
2728/*
2729 * 'mxml_write_node()' - Save an XML node to a file.
2730 */
2731
2732static int /* O - Column or -1 on error */
2733mxml_write_node(mxml_node_t *node, /* I - Node to write */
2734 void *p, /* I - File to write to */
2735 mxml_save_cb_t cb, /* I - Whitespace callback */
2736 int col, /* I - Current column */
2737 _mxml_putc_cb_t putc_cb,/* I - Output callback */
2738 _mxml_global_t *global)/* I - Global data */
2739{
2740 int i, /* Looping var */
2741 width; /* Width of attr + value */
2742 mxml_attr_t *attr; /* Current attribute */
2743 char s[255]; /* Temporary string */
2744
2745
2746 /*
2747 * Print the node value...
2748 */
2749
2750 switch (node->type)
2751 {
2752 case MXML_ELEMENT :
2753 col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
2754
2755 if ((*putc_cb)('<', p) < 0)
2756 return (-1);
2757 if (node->value.element.name[0] == '?' ||
2758 !strncmp(node->value.element.name, "!--", 3) ||
2759 !strncmp(node->value.element.name, "![CDATA[", 8))
2760 {
2761 /*
2762 * Comments, CDATA, and processing instructions do not
2763 * use character entities.
2764 */
2765
2766 const char *ptr; /* Pointer into name */
2767
2768
2769 for (ptr = node->value.element.name; *ptr; ptr ++)
2770 if ((*putc_cb)(*ptr, p) < 0)
2771 return (-1);
2772 }
2773 else if (mxml_write_name(node->value.element.name, p, putc_cb) < 0)
2774 return (-1);
2775
2776 col += strlen(node->value.element.name) + 1;
2777
2778 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
2779 i > 0;
2780 i --, attr ++)
2781 {
2782 width = strlen(attr->name);
2783
2784 if (attr->value)
2785 width += strlen(attr->value) + 3;
2786
2787 if (global->wrap > 0 && (col + width) > global->wrap)
2788 {
2789 if ((*putc_cb)('\n', p) < 0)
2790 return (-1);
2791
2792 col = 0;
2793 }
2794 else
2795 {
2796 if ((*putc_cb)(' ', p) < 0)
2797 return (-1);
2798
2799 col ++;
2800 }
2801
2802 if (mxml_write_name(attr->name, p, putc_cb) < 0)
2803 return (-1);
2804
2805 if (attr->value)
2806 {
2807 if ((*putc_cb)('=', p) < 0)
2808 return (-1);
2809 if ((*putc_cb)('\"', p) < 0)
2810 return (-1);
2811 if (mxml_write_string(attr->value, p, putc_cb) < 0)
2812 return (-1);
2813 if ((*putc_cb)('\"', p) < 0)
2814 return (-1);
2815 }
2816
2817 col += width;
2818 }
2819
2820 if (node->child)
2821 {
2822 /*
2823 * Write children...
2824 */
2825
2826 mxml_node_t *child; /* Current child */
2827
2828
2829 if ((*putc_cb)('>', p) < 0)
2830 return (-1);
2831 else
2832 col ++;
2833
2834 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
2835
2836 for (child = node->child; child; child = child->next)
2837 {
2838 if ((col = mxml_write_node(child, p, cb, col, putc_cb, global)) < 0)
2839 return (-1);
2840 }
2841
2842 /*
2843 * The ? and ! elements are special-cases and have no end tags...
2844 */
2845
2846 if (node->value.element.name[0] != '!' &&
2847 node->value.element.name[0] != '?')
2848 {
2849 col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_CLOSE, col, putc_cb);
2850
2851 if ((*putc_cb)('<', p) < 0)
2852 return (-1);
2853 if ((*putc_cb)('/', p) < 0)
2854 return (-1);
2855 if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
2856 return (-1);
2857 if ((*putc_cb)('>', p) < 0)
2858 return (-1);
2859
2860 col += strlen(node->value.element.name) + 3;
2861
2862 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_CLOSE, col, putc_cb);
2863 }
2864 }
2865 else if (node->value.element.name[0] == '!' ||
2866 node->value.element.name[0] == '?')
2867 {
2868 /*
2869 * The ? and ! elements are special-cases...
2870 */
2871
2872 if ((*putc_cb)('>', p) < 0)
2873 return (-1);
2874 else
2875 col ++;
2876
2877 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
2878 }
2879 else
2880 {
2881 if ((*putc_cb)(' ', p) < 0)
2882 return (-1);
2883 if ((*putc_cb)('/', p) < 0)
2884 return (-1);
2885 if ((*putc_cb)('>', p) < 0)
2886 return (-1);
2887
2888 col += 3;
2889
2890 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
2891 }
2892 break;
2893
2894 case MXML_INTEGER :
2895 if (node->prev)
2896 {
2897 if (global->wrap > 0 && col > global->wrap)
2898 {
2899 if ((*putc_cb)('\n', p) < 0)
2900 return (-1);
2901
2902 col = 0;
2903 }
2904 else if ((*putc_cb)(' ', p) < 0)
2905 return (-1);
2906 else
2907 col ++;
2908 }
2909
2910 sprintf(s, "%d", node->value.integer);
2911 if (mxml_write_string(s, p, putc_cb) < 0)
2912 return (-1);
2913
2914 col += strlen(s);
2915 break;
2916
2917 case MXML_OPAQUE :
2918 if (mxml_write_string(node->value.opaque, p, putc_cb) < 0)
2919 return (-1);
2920
2921 col += strlen(node->value.opaque);
2922 break;
2923
2924 case MXML_REAL :
2925 if (node->prev)
2926 {
2927 if (global->wrap > 0 && col > global->wrap)
2928 {
2929 if ((*putc_cb)('\n', p) < 0)
2930 return (-1);
2931
2932 col = 0;
2933 }
2934 else if ((*putc_cb)(' ', p) < 0)
2935 return (-1);
2936 else
2937 col ++;
2938 }
2939
2940 sprintf(s, "%f", node->value.real);
2941 if (mxml_write_string(s, p, putc_cb) < 0)
2942 return (-1);
2943
2944 col += strlen(s);
2945 break;
2946
2947 case MXML_TEXT :
2948 if (node->value.text.whitespace && col > 0)
2949 {
2950 if (global->wrap > 0 && col > global->wrap)
2951 {
2952 if ((*putc_cb)('\n', p) < 0)
2953 return (-1);
2954
2955 col = 0;
2956 }
2957 else if ((*putc_cb)(' ', p) < 0)
2958 return (-1);
2959 else
2960 col ++;
2961 }
2962
2963 if (mxml_write_string(node->value.text.string, p, putc_cb) < 0)
2964 return (-1);
2965
2966 col += strlen(node->value.text.string);
2967 break;
2968
2969 case MXML_CUSTOM :
2970 if (global->custom_save_cb)
2971 {
2972 char *data; /* Custom data string */
2973 const char *newline; /* Last newline in string */
2974
2975
2976 if ((data = (*global->custom_save_cb)(node)) == NULL)
2977 return (-1);
2978
2979 if (mxml_write_string(data, p, putc_cb) < 0)
2980 return (-1);
2981
2982 if ((newline = strrchr(data, '\n')) == NULL)
2983 col += strlen(data);
2984 else
2985 col = strlen(newline);
2986
2987 free(data);
2988 break;
2989 }
2990
2991 default : /* Should never happen */
2992 return (-1);
2993 }
2994
2995 return (col);
2996}
2997
2998
2999/*
3000 * 'mxml_write_string()' - Write a string, escaping & and < as needed.
3001 */
3002
3003static int /* O - 0 on success, -1 on failure */
3004mxml_write_string(
3005 const char *s, /* I - String to write */
3006 void *p, /* I - Write pointer */
3007 _mxml_putc_cb_t putc_cb) /* I - Write callback */
3008{
3009 const char *name; /* Entity name, if any */
3010
3011
3012 while (*s)
3013 {
3014 if ((name = mxmlEntityGetName(*s)) != NULL)
3015 {
3016 if ((*putc_cb)('&', p) < 0)
3017 return (-1);
3018
3019 while (*name)
3020 {
3021 if ((*putc_cb)(*name, p) < 0)
3022 return (-1);
3023 name ++;
3024 }
3025
3026 if ((*putc_cb)(';', p) < 0)
3027 return (-1);
3028 }
3029 else if ((*putc_cb)(*s, p) < 0)
3030 return (-1);
3031
3032 s ++;
3033 }
3034
3035 return (0);
3036}
3037
3038
3039/*
3040 * 'mxml_write_ws()' - Do whitespace callback...
3041 */
3042
3043static int /* O - New column */
3044mxml_write_ws(mxml_node_t *node, /* I - Current node */
3045 void *p, /* I - Write pointer */
3046 mxml_save_cb_t cb, /* I - Callback function */
3047 int ws, /* I - Where value */
3048 int col, /* I - Current column */
3049 _mxml_putc_cb_t putc_cb) /* I - Write callback */
3050{
3051 const char *s; /* Whitespace string */
3052
3053
3054 if (cb && (s = (*cb)(node, ws)) != NULL)
3055 {
3056 while (*s)
3057 {
3058 if ((*putc_cb)(*s, p) < 0)
3059 return (-1);
3060 else if (*s == '\n')
3061 col = 0;
3062 else if (*s == '\t')
3063 {
3064 col += MXML_TAB;
3065 col = col - (col % MXML_TAB);
3066 }
3067 else
3068 col ++;
3069
3070 s ++;
3071 }
3072 }
3073
3074 return (col);
3075}
3076
3077
3078/*
3079 * End of "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $".
3080 */
diff --git a/pathologist/src/minixml/mxml-get.c b/pathologist/src/minixml/mxml-get.c
new file mode 100644
index 0000000..a5356d5
--- /dev/null
+++ b/pathologist/src/minixml/mxml-get.c
@@ -0,0 +1,471 @@
1/*
2 * "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $"
3 *
4 * Node get functions for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2011 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlGetCDATA() - Get the value for a CDATA node.
19 * mxmlGetCustom() - Get the value for a custom node.
20 * mxmlGetElement() - Get the name for an element node.
21 * mxmlGetFirstChild() - Get the first child of an element node.
22 * mxmlGetInteger() - Get the integer value from the specified node or its
23 * first child.
24 * mxmlGetLastChild() - Get the last child of an element node.
25 * mxmlGetNextSibling() - Get the next node for the current parent.
26 * mxmlGetOpaque() - Get an opaque string value for a node or its first
27 * child.
28 * mxmlGetParent() - Get the parent node.
29 * mxmlGetPrevSibling() - Get the previous node for the current parent.
30 * mxmlGetReal() - Get the real value for a node or its first child.
31 * mxmlGetText() - Get the text value for a node or its first child.
32 * mxmlGetType() - Get the node type.
33 * mxmlGetUserData() - Get the user data pointer for a node.
34 */
35
36/*
37 * Include necessary headers...
38 */
39
40#include "config.h"
41#include "mxml.h"
42
43
44/*
45 * 'mxmlGetCDATA()' - Get the value for a CDATA node.
46 *
47 * @code NULL@ is returned if the node is not a CDATA element.
48 *
49 * @since Mini-XML 2.7@
50 */
51
52const char * /* O - CDATA value or NULL */
53mxmlGetCDATA(mxml_node_t *node) /* I - Node to get */
54{
55 /*
56 * Range check input...
57 */
58
59 if (!node || node->type != MXML_ELEMENT ||
60 strncmp(node->value.element.name, "![CDATA[", 8))
61 return (NULL);
62
63 /*
64 * Return the text following the CDATA declaration...
65 */
66
67 return (node->value.element.name + 8);
68}
69
70
71/*
72 * 'mxmlGetCustom()' - Get the value for a custom node.
73 *
74 * @code NULL@ is returned if the node (or its first child) is not a custom
75 * value node.
76 *
77 * @since Mini-XML 2.7@
78 */
79
80const void * /* O - Custom value or NULL */
81mxmlGetCustom(mxml_node_t *node) /* I - Node to get */
82{
83 /*
84 * Range check input...
85 */
86
87 if (!node)
88 return (NULL);
89
90 /*
91 * Return the integer value...
92 */
93
94 if (node->type == MXML_CUSTOM)
95 return (node->value.custom.data);
96 else if (node->type == MXML_ELEMENT &&
97 node->child &&
98 node->child->type == MXML_CUSTOM)
99 return (node->child->value.custom.data);
100 else
101 return (NULL);
102}
103
104
105/*
106 * 'mxmlGetElement()' - Get the name for an element node.
107 *
108 * @code NULL@ is returned if the node is not an element node.
109 *
110 * @since Mini-XML 2.7@
111 */
112
113const char * /* O - Element name or NULL */
114mxmlGetElement(mxml_node_t *node) /* I - Node to get */
115{
116 /*
117 * Range check input...
118 */
119
120 if (!node || node->type != MXML_ELEMENT)
121 return (NULL);
122
123 /*
124 * Return the element name...
125 */
126
127 return (node->value.element.name);
128}
129
130
131/*
132 * 'mxmlGetFirstChild()' - Get the first child of an element node.
133 *
134 * @code NULL@ is returned if the node is not an element node or if the node
135 * has no children.
136 *
137 * @since Mini-XML 2.7@
138 */
139
140mxml_node_t * /* O - First child or NULL */
141mxmlGetFirstChild(mxml_node_t *node) /* I - Node to get */
142{
143 /*
144 * Range check input...
145 */
146
147 if (!node || node->type != MXML_ELEMENT)
148 return (NULL);
149
150 /*
151 * Return the first child node...
152 */
153
154 return (node->child);
155}
156
157
158/*
159 * 'mxmlGetInteger()' - Get the integer value from the specified node or its
160 * first child.
161 *
162 * 0 is returned if the node (or its first child) is not an integer value node.
163 *
164 * @since Mini-XML 2.7@
165 */
166
167int /* O - Integer value or 0 */
168mxmlGetInteger(mxml_node_t *node) /* I - Node to get */
169{
170 /*
171 * Range check input...
172 */
173
174 if (!node)
175 return (0);
176
177 /*
178 * Return the integer value...
179 */
180
181 if (node->type == MXML_INTEGER)
182 return (node->value.integer);
183 else if (node->type == MXML_ELEMENT &&
184 node->child &&
185 node->child->type == MXML_INTEGER)
186 return (node->child->value.integer);
187 else
188 return (0);
189}
190
191
192/*
193 * 'mxmlGetLastChild()' - Get the last child of an element node.
194 *
195 * @code NULL@ is returned if the node is not an element node or if the node
196 * has no children.
197 *
198 * @since Mini-XML 2.7@
199 */
200
201mxml_node_t * /* O - Last child or NULL */
202mxmlGetLastChild(mxml_node_t *node) /* I - Node to get */
203{
204 /*
205 * Range check input...
206 */
207
208 if (!node || node->type != MXML_ELEMENT)
209 return (NULL);
210
211 /*
212 * Return the node type...
213 */
214
215 return (node->last_child);
216}
217
218
219/*
220 * 'mxmlGetNextSibling()' - Get the next node for the current parent.
221 *
222 * @code NULL@ is returned if this is the last child for the current parent.
223 *
224 * @since Mini-XML 2.7@
225 */
226
227mxml_node_t *
228mxmlGetNextSibling(mxml_node_t *node) /* I - Node to get */
229{
230 /*
231 * Range check input...
232 */
233
234 if (!node)
235 return (NULL);
236
237 /*
238 * Return the node type...
239 */
240
241 return (node->next);
242}
243
244
245/*
246 * 'mxmlGetOpaque()' - Get an opaque string value for a node or its first child.
247 *
248 * @code NULL@ is returned if the node (or its first child) is not an opaque
249 * value node.
250 *
251 * @since Mini-XML 2.7@
252 */
253
254const char * /* O - Opaque string or NULL */
255mxmlGetOpaque(mxml_node_t *node) /* I - Node to get */
256{
257 /*
258 * Range check input...
259 */
260
261 if (!node)
262 return (NULL);
263
264 /*
265 * Return the integer value...
266 */
267
268 if (node->type == MXML_OPAQUE)
269 return (node->value.opaque);
270 else if (node->type == MXML_ELEMENT &&
271 node->child &&
272 node->child->type == MXML_OPAQUE)
273 return (node->child->value.opaque);
274 else
275 return (NULL);
276}
277
278
279/*
280 * 'mxmlGetParent()' - Get the parent node.
281 *
282 * @code NULL@ is returned for a root node.
283 *
284 * @since Mini-XML 2.7@
285 */
286
287mxml_node_t * /* O - Parent node or NULL */
288mxmlGetParent(mxml_node_t *node) /* I - Node to get */
289{
290 /*
291 * Range check input...
292 */
293
294 if (!node)
295 return (NULL);
296
297 /*
298 * Return the node type...
299 */
300
301 return (node->parent);
302}
303
304
305/*
306 * 'mxmlGetPrevSibling()' - Get the previous node for the current parent.
307 *
308 * @code NULL@ is returned if this is the first child for the current parent.
309 *
310 * @since Mini-XML 2.7@
311 */
312
313mxml_node_t * /* O - Previous node or NULL */
314mxmlGetPrevSibling(mxml_node_t *node) /* I - Node to get */
315{
316 /*
317 * Range check input...
318 */
319
320 if (!node)
321 return (NULL);
322
323 /*
324 * Return the node type...
325 */
326
327 return (node->prev);
328}
329
330
331/*
332 * 'mxmlGetReal()' - Get the real value for a node or its first child.
333 *
334 * 0.0 is returned if the node (or its first child) is not a real value node.
335 *
336 * @since Mini-XML 2.7@
337 */
338
339double /* O - Real value or 0.0 */
340mxmlGetReal(mxml_node_t *node) /* I - Node to get */
341{
342 /*
343 * Range check input...
344 */
345
346 if (!node)
347 return (0.0);
348
349 /*
350 * Return the integer value...
351 */
352
353 if (node->type == MXML_REAL)
354 return (node->value.real);
355 else if (node->type == MXML_ELEMENT &&
356 node->child &&
357 node->child->type == MXML_REAL)
358 return (node->child->value.real);
359 else
360 return (0.0);
361}
362
363
364/*
365 * 'mxmlGetText()' - Get the text value for a node or its first child.
366 *
367 * @code NULL@ is returned if the node (or its first child) is not a text node.
368 * The "whitespace" argument can be NULL.
369 *
370 * @since Mini-XML 2.7@
371 */
372
373const char * /* O - Text string or NULL */
374mxmlGetText(mxml_node_t *node, /* I - Node to get */
375 int *whitespace) /* O - 1 if string is preceded by whitespace, 0 otherwise */
376{
377 /*
378 * Range check input...
379 */
380
381 if (!node)
382 {
383 if (whitespace)
384 *whitespace = 0;
385
386 return (NULL);
387 }
388
389 /*
390 * Return the integer value...
391 */
392
393 if (node->type == MXML_TEXT)
394 {
395 if (whitespace)
396 *whitespace = node->value.text.whitespace;
397
398 return (node->value.text.string);
399 }
400 else if (node->type == MXML_ELEMENT &&
401 node->child &&
402 node->child->type == MXML_TEXT)
403 {
404 if (whitespace)
405 *whitespace = node->child->value.text.whitespace;
406
407 return (node->child->value.text.string);
408 }
409 else
410 {
411 if (whitespace)
412 *whitespace = 0;
413
414 return (NULL);
415 }
416}
417
418
419/*
420 * 'mxmlGetType()' - Get the node type.
421 *
422 * @code MXML_IGNORE@ is returned if "node" is @code NULL@.
423 *
424 * @since Mini-XML 2.7@
425 */
426
427mxml_type_t /* O - Type of node */
428mxmlGetType(mxml_node_t *node) /* I - Node to get */
429{
430 /*
431 * Range check input...
432 */
433
434 if (!node)
435 return (MXML_IGNORE);
436
437 /*
438 * Return the node type...
439 */
440
441 return (node->type);
442}
443
444
445/*
446 * 'mxmlGetUserData()' - Get the user data pointer for a node.
447 *
448 * @since Mini-XML 2.7@
449 */
450
451void * /* O - User data pointer */
452mxmlGetUserData(mxml_node_t *node) /* I - Node to get */
453{
454 /*
455 * Range check input...
456 */
457
458 if (!node)
459 return (NULL);
460
461 /*
462 * Return the user data pointer...
463 */
464
465 return (node->user_data);
466}
467
468
469/*
470 * End of "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $".
471 */
diff --git a/pathologist/src/minixml/mxml-index.c b/pathologist/src/minixml/mxml-index.c
new file mode 100644
index 0000000..b6efc66
--- /dev/null
+++ b/pathologist/src/minixml/mxml-index.c
@@ -0,0 +1,662 @@
1/*
2 * "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $"
3 *
4 * Index support code for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2011 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 */
19
20/*
21 * Include necessary headers...
22 */
23
24#include "config.h"
25#include "mxml.h"
26
27
28/*
29 * Sort functions...
30 */
31
32static int index_compare(mxml_index_t *ind, mxml_node_t *first,
33 mxml_node_t *second);
34static int index_find(mxml_index_t *ind, const char *element,
35 const char *value, mxml_node_t *node);
36static void index_sort(mxml_index_t *ind, int left, int right);
37
38
39/*
40 * 'mxmlIndexDelete()' - Delete an index.
41 */
42
43void
44mxmlIndexDelete(mxml_index_t *ind) /* I - Index to delete */
45{
46 /*
47 * Range check input..
48 */
49
50 if (!ind)
51 return;
52
53 /*
54 * Free memory...
55 */
56
57 if (ind->attr)
58 free(ind->attr);
59
60 if (ind->alloc_nodes)
61 free(ind->nodes);
62
63 free(ind);
64}
65
66
67/*
68 * 'mxmlIndexEnum()' - Return the next node in the index.
69 *
70 * Nodes are returned in the sorted order of the index.
71 */
72
73mxml_node_t * /* O - Next node or NULL if there is none */
74mxmlIndexEnum(mxml_index_t *ind) /* I - Index to enumerate */
75{
76 /*
77 * Range check input...
78 */
79
80 if (!ind)
81 return (NULL);
82
83 /*
84 * Return the next node...
85 */
86
87 if (ind->cur_node < ind->num_nodes)
88 return (ind->nodes[ind->cur_node ++]);
89 else
90 return (NULL);
91}
92
93
94/*
95 * 'mxmlIndexFind()' - Find the next matching node.
96 *
97 * You should call mxmlIndexReset() prior to using this function for
98 * the first time with a particular set of "element" and "value"
99 * strings. Passing NULL for both "element" and "value" is equivalent
100 * to calling mxmlIndexEnum().
101 */
102
103mxml_node_t * /* O - Node or NULL if none found */
104mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */
105 const char *element, /* I - Element name to find, if any */
106 const char *value) /* I - Attribute value, if any */
107{
108 int diff, /* Difference between names */
109 current, /* Current entity in search */
110 first, /* First entity in search */
111 last; /* Last entity in search */
112
113
114#ifdef DEBUG
115 printf("mxmlIndexFind(ind=%p, element=\"%s\", value=\"%s\")\n",
116 ind, element ? element : "(null)", value ? value : "(null)");
117#endif /* DEBUG */
118
119 /*
120 * Range check input...
121 */
122
123 if (!ind || (!ind->attr && value))
124 {
125#ifdef DEBUG
126 puts(" returning NULL...");
127 printf(" ind->attr=\"%s\"\n", ind->attr ? ind->attr : "(null)");
128#endif /* DEBUG */
129
130 return (NULL);
131 }
132
133 /*
134 * If both element and value are NULL, just enumerate the nodes in the
135 * index...
136 */
137
138 if (!element && !value)
139 return (mxmlIndexEnum(ind));
140
141 /*
142 * If there are no nodes in the index, return NULL...
143 */
144
145 if (!ind->num_nodes)
146 {
147#ifdef DEBUG
148 puts(" returning NULL...");
149 puts(" no nodes!");
150#endif /* DEBUG */
151
152 return (NULL);
153 }
154
155 /*
156 * If cur_node == 0, then find the first matching node...
157 */
158
159 if (ind->cur_node == 0)
160 {
161 /*
162 * Find the first node using a modified binary search algorithm...
163 */
164
165 first = 0;
166 last = ind->num_nodes - 1;
167
168#ifdef DEBUG
169 printf(" find first time, num_nodes=%d...\n", ind->num_nodes);
170#endif /* DEBUG */
171
172 while ((last - first) > 1)
173 {
174 current = (first + last) / 2;
175
176#ifdef DEBUG
177 printf(" first=%d, last=%d, current=%d\n", first, last, current);
178#endif /* DEBUG */
179
180 if ((diff = index_find(ind, element, value, ind->nodes[current])) == 0)
181 {
182 /*
183 * Found a match, move back to find the first...
184 */
185
186#ifdef DEBUG
187 puts(" match!");
188#endif /* DEBUG */
189
190 while (current > 0 &&
191 !index_find(ind, element, value, ind->nodes[current - 1]))
192 current --;
193
194#ifdef DEBUG
195 printf(" returning first match=%d\n", current);
196#endif /* DEBUG */
197
198 /*
199 * Return the first match and save the index to the next...
200 */
201
202 ind->cur_node = current + 1;
203
204 return (ind->nodes[current]);
205 }
206 else if (diff < 0)
207 last = current;
208 else
209 first = current;
210
211#ifdef DEBUG
212 printf(" diff=%d\n", diff);
213#endif /* DEBUG */
214 }
215
216 /*
217 * If we get this far, then we found exactly 0 or 1 matches...
218 */
219
220 for (current = first; current <= last; current ++)
221 if (!index_find(ind, element, value, ind->nodes[current]))
222 {
223 /*
224 * Found exactly one (or possibly two) match...
225 */
226
227#ifdef DEBUG
228 printf(" returning only match %d...\n", current);
229#endif /* DEBUG */
230
231 ind->cur_node = current + 1;
232
233 return (ind->nodes[current]);
234 }
235
236 /*
237 * No matches...
238 */
239
240 ind->cur_node = ind->num_nodes;
241
242#ifdef DEBUG
243 puts(" returning NULL...");
244#endif /* DEBUG */
245
246 return (NULL);
247 }
248 else if (ind->cur_node < ind->num_nodes &&
249 !index_find(ind, element, value, ind->nodes[ind->cur_node]))
250 {
251 /*
252 * Return the next matching node...
253 */
254
255#ifdef DEBUG
256 printf(" returning next match %d...\n", ind->cur_node);
257#endif /* DEBUG */
258
259 return (ind->nodes[ind->cur_node ++]);
260 }
261
262 /*
263 * If we get this far, then we have no matches...
264 */
265
266 ind->cur_node = ind->num_nodes;
267
268#ifdef DEBUG
269 puts(" returning NULL...");
270#endif /* DEBUG */
271
272 return (NULL);
273}
274
275
276/*
277 * 'mxmlIndexGetCount()' - Get the number of nodes in an index.
278 *
279 * @since Mini-XML 2.7@
280 */
281
282int /* I - Number of nodes in index */
283mxmlIndexGetCount(mxml_index_t *ind) /* I - Index of nodes */
284{
285 /*
286 * Range check input...
287 */
288
289 if (!ind)
290 return (0);
291
292 /*
293 * Return the number of nodes in the index...
294 */
295
296 return (ind->num_nodes);
297}
298
299
300/*
301 * 'mxmlIndexNew()' - Create a new index.
302 *
303 * The index will contain all nodes that contain the named element and/or
304 * attribute. If both "element" and "attr" are NULL, then the index will
305 * contain a sorted list of the elements in the node tree. Nodes are
306 * sorted by element name and optionally by attribute value if the "attr"
307 * argument is not NULL.
308 */
309
310mxml_index_t * /* O - New index */
311mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */
312 const char *element, /* I - Element to index or NULL for all */
313 const char *attr) /* I - Attribute to index or NULL for none */
314{
315 mxml_index_t *ind; /* New index */
316 mxml_node_t *current, /* Current node in index */
317 **temp; /* Temporary node pointer array */
318
319
320 /*
321 * Range check input...
322 */
323
324#ifdef DEBUG
325 printf("mxmlIndexNew(node=%p, element=\"%s\", attr=\"%s\")\n",
326 node, element ? element : "(null)", attr ? attr : "(null)");
327#endif /* DEBUG */
328
329 if (!node)
330 return (NULL);
331
332 /*
333 * Create a new index...
334 */
335
336 if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL)
337 {
338 mxml_error("Unable to allocate %d bytes for index - %s",
339 sizeof(mxml_index_t), strerror(errno));
340 return (NULL);
341 }
342
343 if (attr)
344 ind->attr = strdup(attr);
345
346 if (!element && !attr)
347 current = node;
348 else
349 current = mxmlFindElement(node, node, element, attr, NULL, MXML_DESCEND);
350
351 while (current)
352 {
353 if (ind->num_nodes >= ind->alloc_nodes)
354 {
355 if (!ind->alloc_nodes)
356 temp = malloc(64 * sizeof(mxml_node_t *));
357 else
358 temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *));
359
360 if (!temp)
361 {
362 /*
363 * Unable to allocate memory for the index, so abort...
364 */
365
366 mxml_error("Unable to allocate %d bytes for index: %s",
367 (ind->alloc_nodes + 64) * sizeof(mxml_node_t *),
368 strerror(errno));
369
370 mxmlIndexDelete(ind);
371 return (NULL);
372 }
373
374 ind->nodes = temp;
375 ind->alloc_nodes += 64;
376 }
377
378 ind->nodes[ind->num_nodes ++] = current;
379
380 current = mxmlFindElement(current, node, element, attr, NULL, MXML_DESCEND);
381 }
382
383 /*
384 * Sort nodes based upon the search criteria...
385 */
386
387#ifdef DEBUG
388 {
389 int i; /* Looping var */
390
391
392 printf("%d node(s) in index.\n\n", ind->num_nodes);
393
394 if (attr)
395 {
396 printf("Node Address Element %s\n", attr);
397 puts("-------- -------- -------------- ------------------------------");
398
399 for (i = 0; i < ind->num_nodes; i ++)
400 printf("%8d %-8p %-14.14s %s\n", i, ind->nodes[i],
401 ind->nodes[i]->value.element.name,
402 mxmlElementGetAttr(ind->nodes[i], attr));
403 }
404 else
405 {
406 puts("Node Address Element");
407 puts("-------- -------- --------------");
408
409 for (i = 0; i < ind->num_nodes; i ++)
410 printf("%8d %-8p %s\n", i, ind->nodes[i],
411 ind->nodes[i]->value.element.name);
412 }
413
414 putchar('\n');
415 }
416#endif /* DEBUG */
417
418 if (ind->num_nodes > 1)
419 index_sort(ind, 0, ind->num_nodes - 1);
420
421#ifdef DEBUG
422 {
423 int i; /* Looping var */
424
425
426 puts("After sorting:\n");
427
428 if (attr)
429 {
430 printf("Node Address Element %s\n", attr);
431 puts("-------- -------- -------------- ------------------------------");
432
433 for (i = 0; i < ind->num_nodes; i ++)
434 printf("%8d %-8p %-14.14s %s\n", i, ind->nodes[i],
435 ind->nodes[i]->value.element.name,
436 mxmlElementGetAttr(ind->nodes[i], attr));
437 }
438 else
439 {
440 puts("Node Address Element");
441 puts("-------- -------- --------------");
442
443 for (i = 0; i < ind->num_nodes; i ++)
444 printf("%8d %-8p %s\n", i, ind->nodes[i],
445 ind->nodes[i]->value.element.name);
446 }
447
448 putchar('\n');
449 }
450#endif /* DEBUG */
451
452 /*
453 * Return the new index...
454 */
455
456 return (ind);
457}
458
459
460/*
461 * 'mxmlIndexReset()' - Reset the enumeration/find pointer in the index and
462 * return the first node in the index.
463 *
464 * This function should be called prior to using mxmlIndexEnum() or
465 * mxmlIndexFind() for the first time.
466 */
467
468mxml_node_t * /* O - First node or NULL if there is none */
469mxmlIndexReset(mxml_index_t *ind) /* I - Index to reset */
470{
471#ifdef DEBUG
472 printf("mxmlIndexReset(ind=%p)\n", ind);
473#endif /* DEBUG */
474
475 /*
476 * Range check input...
477 */
478
479 if (!ind)
480 return (NULL);
481
482 /*
483 * Set the index to the first element...
484 */
485
486 ind->cur_node = 0;
487
488 /*
489 * Return the first node...
490 */
491
492 if (ind->num_nodes)
493 return (ind->nodes[0]);
494 else
495 return (NULL);
496}
497
498
499/*
500 * 'index_compare()' - Compare two nodes.
501 */
502
503static int /* O - Result of comparison */
504index_compare(mxml_index_t *ind, /* I - Index */
505 mxml_node_t *first, /* I - First node */
506 mxml_node_t *second) /* I - Second node */
507{
508 int diff; /* Difference */
509
510
511 /*
512 * Check the element name...
513 */
514
515 if ((diff = strcmp(first->value.element.name,
516 second->value.element.name)) != 0)
517 return (diff);
518
519 /*
520 * Check the attribute value...
521 */
522
523 if (ind->attr)
524 {
525 if ((diff = strcmp(mxmlElementGetAttr(first, ind->attr),
526 mxmlElementGetAttr(second, ind->attr))) != 0)
527 return (diff);
528 }
529
530 /*
531 * No difference, return 0...
532 */
533
534 return (0);
535}
536
537
538/*
539 * 'index_find()' - Compare a node with index values.
540 */
541
542static int /* O - Result of comparison */
543index_find(mxml_index_t *ind, /* I - Index */
544 const char *element, /* I - Element name or NULL */
545 const char *value, /* I - Attribute value or NULL */
546 mxml_node_t *node) /* I - Node */
547{
548 int diff; /* Difference */
549
550
551 /*
552 * Check the element name...
553 */
554
555 if (element)
556 {
557 if ((diff = strcmp(element, node->value.element.name)) != 0)
558 return (diff);
559 }
560
561 /*
562 * Check the attribute value...
563 */
564
565 if (value)
566 {
567 if ((diff = strcmp(value, mxmlElementGetAttr(node, ind->attr))) != 0)
568 return (diff);
569 }
570
571 /*
572 * No difference, return 0...
573 */
574
575 return (0);
576}
577
578
579/*
580 * 'index_sort()' - Sort the nodes in the index...
581 *
582 * This function implements the classic quicksort algorithm...
583 */
584
585static void
586index_sort(mxml_index_t *ind, /* I - Index to sort */
587 int left, /* I - Left node in partition */
588 int right) /* I - Right node in partition */
589{
590 mxml_node_t *pivot, /* Pivot node */
591 *temp; /* Swap node */
592 int templ, /* Temporary left node */
593 tempr; /* Temporary right node */
594
595
596 /*
597 * Loop until we have sorted all the way to the right...
598 */
599
600 do
601 {
602 /*
603 * Sort the pivot in the current partition...
604 */
605
606 pivot = ind->nodes[left];
607
608 for (templ = left, tempr = right; templ < tempr;)
609 {
610 /*
611 * Move left while left node <= pivot node...
612 */
613
614 while ((templ < right) &&
615 index_compare(ind, ind->nodes[templ], pivot) <= 0)
616 templ ++;
617
618 /*
619 * Move right while right node > pivot node...
620 */
621
622 while ((tempr > left) &&
623 index_compare(ind, ind->nodes[tempr], pivot) > 0)
624 tempr --;
625
626 /*
627 * Swap nodes if needed...
628 */
629
630 if (templ < tempr)
631 {
632 temp = ind->nodes[templ];
633 ind->nodes[templ] = ind->nodes[tempr];
634 ind->nodes[tempr] = temp;
635 }
636 }
637
638 /*
639 * When we get here, the right (tempr) node is the new position for the
640 * pivot node...
641 */
642
643 if (index_compare(ind, pivot, ind->nodes[tempr]) > 0)
644 {
645 ind->nodes[left] = ind->nodes[tempr];
646 ind->nodes[tempr] = pivot;
647 }
648
649 /*
650 * Recursively sort the left partition as needed...
651 */
652
653 if (left < (tempr - 1))
654 index_sort(ind, left, tempr - 1);
655 }
656 while (right > (left = tempr + 1));
657}
658
659
660/*
661 * End of "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $".
662 */
diff --git a/pathologist/src/minixml/mxml-node.c b/pathologist/src/minixml/mxml-node.c
new file mode 100644
index 0000000..44af759
--- /dev/null
+++ b/pathologist/src/minixml/mxml-node.c
@@ -0,0 +1,807 @@
1/*
2 * "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $"
3 *
4 * Node support code for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2011 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlAdd() - Add a node to a tree.
19 * mxmlDelete() - Delete a node and all of its children.
20 * mxmlGetRefCount() - Get the current reference (use) count for a node.
21 * mxmlNewCDATA() - Create a new CDATA node.
22 * mxmlNewCustom() - Create a new custom data node.
23 * mxmlNewElement() - Create a new element node.
24 * mxmlNewInteger() - Create a new integer node.
25 * mxmlNewOpaque() - Create a new opaque string.
26 * mxmlNewReal() - Create a new real number node.
27 * mxmlNewText() - Create a new text fragment node.
28 * mxmlNewTextf() - Create a new formatted text fragment node.
29 * mxmlRemove() - Remove a node from its parent.
30 * mxmlNewXML() - Create a new XML document tree.
31 * mxmlRelease() - Release a node.
32 * mxmlRetain() - Retain a node.
33 * mxml_new() - Create a new node.
34 */
35
36/*
37 * Include necessary headers...
38 */
39
40#include "config.h"
41#include "mxml.h"
42
43
44/*
45 * Local functions...
46 */
47
48static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type);
49
50
51/*
52 * 'mxmlAdd()' - Add a node to a tree.
53 *
54 * Adds the specified node to the parent. If the child argument is not
55 * NULL, puts the new node before or after the specified child depending
56 * on the value of the where argument. If the child argument is NULL,
57 * puts the new node at the beginning of the child list (MXML_ADD_BEFORE)
58 * or at the end of the child list (MXML_ADD_AFTER). The constant
59 * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
60 */
61
62void
63mxmlAdd(mxml_node_t *parent, /* I - Parent node */
64 int where, /* I - Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER */
65 mxml_node_t *child, /* I - Child node for where or MXML_ADD_TO_PARENT */
66 mxml_node_t *node) /* I - Node to add */
67{
68#ifdef DEBUG
69 fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
70 where, child, node);
71#endif /* DEBUG */
72
73 /*
74 * Range check input...
75 */
76
77 if (!parent || !node)
78 return;
79
80#if DEBUG > 1
81 fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
82 if (parent)
83 {
84 fprintf(stderr, " BEFORE: parent->child=%p\n", parent->child);
85 fprintf(stderr, " BEFORE: parent->last_child=%p\n", parent->last_child);
86 fprintf(stderr, " BEFORE: parent->prev=%p\n", parent->prev);
87 fprintf(stderr, " BEFORE: parent->next=%p\n", parent->next);
88 }
89#endif /* DEBUG > 1 */
90
91 /*
92 * Remove the node from any existing parent...
93 */
94
95 if (node->parent)
96 mxmlRemove(node);
97
98 /*
99 * Reset pointers...
100 */
101
102 node->parent = parent;
103
104 switch (where)
105 {
106 case MXML_ADD_BEFORE :
107 if (!child || child == parent->child || child->parent != parent)
108 {
109 /*
110 * Insert as first node under parent...
111 */
112
113 node->next = parent->child;
114
115 if (parent->child)
116 parent->child->prev = node;
117 else
118 parent->last_child = node;
119
120 parent->child = node;
121 }
122 else
123 {
124 /*
125 * Insert node before this child...
126 */
127
128 node->next = child;
129 node->prev = child->prev;
130
131 if (child->prev)
132 child->prev->next = node;
133 else
134 parent->child = node;
135
136 child->prev = node;
137 }
138 break;
139
140 case MXML_ADD_AFTER :
141 if (!child || child == parent->last_child || child->parent != parent)
142 {
143 /*
144 * Insert as last node under parent...
145 */
146
147 node->parent = parent;
148 node->prev = parent->last_child;
149
150 if (parent->last_child)
151 parent->last_child->next = node;
152 else
153 parent->child = node;
154
155 parent->last_child = node;
156 }
157 else
158 {
159 /*
160 * Insert node after this child...
161 */
162
163 node->prev = child;
164 node->next = child->next;
165
166 if (child->next)
167 child->next->prev = node;
168 else
169 parent->last_child = node;
170
171 child->next = node;
172 }
173 break;
174 }
175
176#if DEBUG > 1
177 fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
178 if (parent)
179 {
180 fprintf(stderr, " AFTER: parent->child=%p\n", parent->child);
181 fprintf(stderr, " AFTER: parent->last_child=%p\n", parent->last_child);
182 fprintf(stderr, " AFTER: parent->prev=%p\n", parent->prev);
183 fprintf(stderr, " AFTER: parent->next=%p\n", parent->next);
184 }
185#endif /* DEBUG > 1 */
186}
187
188
189/*
190 * 'mxmlDelete()' - Delete a node and all of its children.
191 *
192 * If the specified node has a parent, this function first removes the
193 * node from its parent using the mxmlRemove() function.
194 */
195
196void
197mxmlDelete(mxml_node_t *node) /* I - Node to delete */
198{
199 int i; /* Looping var */
200
201
202#ifdef DEBUG
203 fprintf(stderr, "mxmlDelete(node=%p)\n", node);
204#endif /* DEBUG */
205
206 /*
207 * Range check input...
208 */
209
210 if (!node)
211 return;
212
213 /*
214 * Remove the node from its parent, if any...
215 */
216
217 mxmlRemove(node);
218
219 /*
220 * Delete children...
221 */
222
223 while (node->child)
224 mxmlDelete(node->child);
225
226 /*
227 * Now delete any node data...
228 */
229
230 switch (node->type)
231 {
232 case MXML_ELEMENT :
233 if (node->value.element.name)
234 free(node->value.element.name);
235
236 if (node->value.element.num_attrs)
237 {
238 for (i = 0; i < node->value.element.num_attrs; i ++)
239 {
240 if (node->value.element.attrs[i].name)
241 free(node->value.element.attrs[i].name);
242 if (node->value.element.attrs[i].value)
243 free(node->value.element.attrs[i].value);
244 }
245
246 free(node->value.element.attrs);
247 }
248 break;
249 case MXML_INTEGER :
250 /* Nothing to do */
251 break;
252 case MXML_OPAQUE :
253 if (node->value.opaque)
254 free(node->value.opaque);
255 break;
256 case MXML_REAL :
257 /* Nothing to do */
258 break;
259 case MXML_TEXT :
260 if (node->value.text.string)
261 free(node->value.text.string);
262 break;
263 case MXML_CUSTOM :
264 if (node->value.custom.data &&
265 node->value.custom.destroy)
266 (*(node->value.custom.destroy))(node->value.custom.data);
267 break;
268 default :
269 break;
270 }
271
272 /*
273 * Free this node...
274 */
275
276 free(node);
277}
278
279
280/*
281 * 'mxmlGetRefCount()' - Get the current reference (use) count for a node.
282 *
283 * The initial reference count of new nodes is 1. Use the @link mxmlRetain@
284 * and @link mxmlRelease@ functions to increment and decrement a node's
285 * reference count.
286 *
287 * @since Mini-XML 2.7@.
288 */
289
290int /* O - Reference count */
291mxmlGetRefCount(mxml_node_t *node) /* I - Node */
292{
293 /*
294 * Range check input...
295 */
296
297 if (!node)
298 return (0);
299
300 /*
301 * Return the reference count...
302 */
303
304 return (node->ref_count);
305}
306
307
308/*
309 * 'mxmlNewCDATA()' - Create a new CDATA node.
310 *
311 * The new CDATA node is added to the end of the specified parent's child
312 * list. The constant MXML_NO_PARENT can be used to specify that the new
313 * CDATA node has no parent. The data string must be nul-terminated and
314 * is copied into the new node. CDATA nodes use the MXML_ELEMENT type.
315 *
316 * @since Mini-XML 2.3@
317 */
318
319mxml_node_t * /* O - New node */
320mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
321 const char *data) /* I - Data string */
322{
323 mxml_node_t *node; /* New node */
324
325
326#ifdef DEBUG
327 fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
328 parent, data ? data : "(null)");
329#endif /* DEBUG */
330
331 /*
332 * Range check input...
333 */
334
335 if (!data)
336 return (NULL);
337
338 /*
339 * Create the node and set the name value...
340 */
341
342 if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
343 node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
344
345 return (node);
346}
347
348
349/*
350 * 'mxmlNewCustom()' - Create a new custom data node.
351 *
352 * The new custom node is added to the end of the specified parent's child
353 * list. The constant MXML_NO_PARENT can be used to specify that the new
354 * element node has no parent. NULL can be passed when the data in the
355 * node is not dynamically allocated or is separately managed.
356 *
357 * @since Mini-XML 2.1@
358 */
359
360mxml_node_t * /* O - New node */
361mxmlNewCustom(
362 mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
363 void *data, /* I - Pointer to data */
364 mxml_custom_destroy_cb_t destroy) /* I - Function to destroy data */
365{
366 mxml_node_t *node; /* New node */
367
368
369#ifdef DEBUG
370 fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
371 data, destroy);
372#endif /* DEBUG */
373
374 /*
375 * Create the node and set the value...
376 */
377
378 if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL)
379 {
380 node->value.custom.data = data;
381 node->value.custom.destroy = destroy;
382 }
383
384 return (node);
385}
386
387
388/*
389 * 'mxmlNewElement()' - Create a new element node.
390 *
391 * The new element node is added to the end of the specified parent's child
392 * list. The constant MXML_NO_PARENT can be used to specify that the new
393 * element node has no parent.
394 */
395
396mxml_node_t * /* O - New node */
397mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
398 const char *name) /* I - Name of element */
399{
400 mxml_node_t *node; /* New node */
401
402
403#ifdef DEBUG
404 fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
405 name ? name : "(null)");
406#endif /* DEBUG */
407
408 /*
409 * Range check input...
410 */
411
412 if (!name)
413 return (NULL);
414
415 /*
416 * Create the node and set the element name...
417 */
418
419 if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
420 node->value.element.name = strdup(name);
421
422 return (node);
423}
424
425
426/*
427 * 'mxmlNewInteger()' - Create a new integer node.
428 *
429 * The new integer node is added to the end of the specified parent's child
430 * list. The constant MXML_NO_PARENT can be used to specify that the new
431 * integer node has no parent.
432 */
433
434mxml_node_t * /* O - New node */
435mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
436 int integer) /* I - Integer value */
437{
438 mxml_node_t *node; /* New node */
439
440
441#ifdef DEBUG
442 fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
443#endif /* DEBUG */
444
445 /*
446 * Create the node and set the element name...
447 */
448
449 if ((node = mxml_new(parent, MXML_INTEGER)) != NULL)
450 node->value.integer = integer;
451
452 return (node);
453}
454
455
456/*
457 * 'mxmlNewOpaque()' - Create a new opaque string.
458 *
459 * The new opaque node is added to the end of the specified parent's child
460 * list. The constant MXML_NO_PARENT can be used to specify that the new
461 * opaque node has no parent. The opaque string must be nul-terminated and
462 * is copied into the new node.
463 */
464
465mxml_node_t * /* O - New node */
466mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
467 const char *opaque) /* I - Opaque string */
468{
469 mxml_node_t *node; /* New node */
470
471
472#ifdef DEBUG
473 fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
474 opaque ? opaque : "(null)");
475#endif /* DEBUG */
476
477 /*
478 * Range check input...
479 */
480
481 if (!opaque)
482 return (NULL);
483
484 /*
485 * Create the node and set the element name...
486 */
487
488 if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL)
489 node->value.opaque = strdup(opaque);
490
491 return (node);
492}
493
494
495/*
496 * 'mxmlNewReal()' - Create a new real number node.
497 *
498 * The new real number node is added to the end of the specified parent's
499 * child list. The constant MXML_NO_PARENT can be used to specify that
500 * the new real number node has no parent.
501 */
502
503mxml_node_t * /* O - New node */
504mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
505 double real) /* I - Real number value */
506{
507 mxml_node_t *node; /* New node */
508
509
510#ifdef DEBUG
511 fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
512#endif /* DEBUG */
513
514 /*
515 * Create the node and set the element name...
516 */
517
518 if ((node = mxml_new(parent, MXML_REAL)) != NULL)
519 node->value.real = real;
520
521 return (node);
522}
523
524
525/*
526 * 'mxmlNewText()' - Create a new text fragment node.
527 *
528 * The new text node is added to the end of the specified parent's child
529 * list. The constant MXML_NO_PARENT can be used to specify that the new
530 * text node has no parent. The whitespace parameter is used to specify
531 * whether leading whitespace is present before the node. The text
532 * string must be nul-terminated and is copied into the new node.
533 */
534
535mxml_node_t * /* O - New node */
536mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
537 int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
538 const char *string) /* I - String */
539{
540 mxml_node_t *node; /* New node */
541
542
543#ifdef DEBUG
544 fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
545 parent, whitespace, string ? string : "(null)");
546#endif /* DEBUG */
547
548 /*
549 * Range check input...
550 */
551
552 if (!string)
553 return (NULL);
554
555 /*
556 * Create the node and set the text value...
557 */
558
559 if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
560 {
561 node->value.text.whitespace = whitespace;
562 node->value.text.string = strdup(string);
563 }
564
565 return (node);
566}
567
568
569/*
570 * 'mxmlNewTextf()' - Create a new formatted text fragment node.
571 *
572 * The new text node is added to the end of the specified parent's child
573 * list. The constant MXML_NO_PARENT can be used to specify that the new
574 * text node has no parent. The whitespace parameter is used to specify
575 * whether leading whitespace is present before the node. The format
576 * string must be nul-terminated and is formatted into the new node.
577 */
578
579mxml_node_t * /* O - New node */
580mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
581 int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
582 const char *format, /* I - Printf-style frmat string */
583 ...) /* I - Additional args as needed */
584{
585 mxml_node_t *node; /* New node */
586 va_list ap; /* Pointer to arguments */
587
588
589#ifdef DEBUG
590 fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n",
591 parent, whitespace, format ? format : "(null)");
592#endif /* DEBUG */
593
594 /*
595 * Range check input...
596 */
597
598 if (!format)
599 return (NULL);
600
601 /*
602 * Create the node and set the text value...
603 */
604
605 if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
606 {
607 va_start(ap, format);
608
609 node->value.text.whitespace = whitespace;
610 node->value.text.string = _mxml_vstrdupf(format, ap);
611
612 va_end(ap);
613 }
614
615 return (node);
616}
617
618
619/*
620 * 'mxmlRemove()' - Remove a node from its parent.
621 *
622 * Does not free memory used by the node - use mxmlDelete() for that.
623 * This function does nothing if the node has no parent.
624 */
625
626void
627mxmlRemove(mxml_node_t *node) /* I - Node to remove */
628{
629#ifdef DEBUG
630 fprintf(stderr, "mxmlRemove(node=%p)\n", node);
631#endif /* DEBUG */
632
633 /*
634 * Range check input...
635 */
636
637 if (!node || !node->parent)
638 return;
639
640 /*
641 * Remove from parent...
642 */
643
644#if DEBUG > 1
645 fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
646 if (node->parent)
647 {
648 fprintf(stderr, " BEFORE: node->parent->child=%p\n", node->parent->child);
649 fprintf(stderr, " BEFORE: node->parent->last_child=%p\n", node->parent->last_child);
650 }
651 fprintf(stderr, " BEFORE: node->child=%p\n", node->child);
652 fprintf(stderr, " BEFORE: node->last_child=%p\n", node->last_child);
653 fprintf(stderr, " BEFORE: node->prev=%p\n", node->prev);
654 fprintf(stderr, " BEFORE: node->next=%p\n", node->next);
655#endif /* DEBUG > 1 */
656
657 if (node->prev)
658 node->prev->next = node->next;
659 else
660 node->parent->child = node->next;
661
662 if (node->next)
663 node->next->prev = node->prev;
664 else
665 node->parent->last_child = node->prev;
666
667 node->parent = NULL;
668 node->prev = NULL;
669 node->next = NULL;
670
671#if DEBUG > 1
672 fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
673 if (node->parent)
674 {
675 fprintf(stderr, " AFTER: node->parent->child=%p\n", node->parent->child);
676 fprintf(stderr, " AFTER: node->parent->last_child=%p\n", node->parent->last_child);
677 }
678 fprintf(stderr, " AFTER: node->child=%p\n", node->child);
679 fprintf(stderr, " AFTER: node->last_child=%p\n", node->last_child);
680 fprintf(stderr, " AFTER: node->prev=%p\n", node->prev);
681 fprintf(stderr, " AFTER: node->next=%p\n", node->next);
682#endif /* DEBUG > 1 */
683}
684
685
686/*
687 * 'mxmlNewXML()' - Create a new XML document tree.
688 *
689 * The "version" argument specifies the version number to put in the
690 * ?xml element node. If NULL, version 1.0 is assumed.
691 *
692 * @since Mini-XML 2.3@
693 */
694
695mxml_node_t * /* O - New ?xml node */
696mxmlNewXML(const char *version) /* I - Version number to use */
697{
698 char element[1024]; /* Element text */
699
700
701 snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?",
702 version ? version : "1.0");
703
704 return (mxmlNewElement(NULL, element));
705}
706
707
708/*
709 * 'mxmlRelease()' - Release a node.
710 *
711 * When the reference count reaches zero, the node (and any children)
712 * is deleted via mxmlDelete().
713 *
714 * @since Mini-XML 2.3@
715 */
716
717int /* O - New reference count */
718mxmlRelease(mxml_node_t *node) /* I - Node */
719{
720 if (node)
721 {
722 if ((-- node->ref_count) <= 0)
723 {
724 mxmlDelete(node);
725 return (0);
726 }
727 else
728 return (node->ref_count);
729 }
730 else
731 return (-1);
732}
733
734
735/*
736 * 'mxmlRetain()' - Retain a node.
737 *
738 * @since Mini-XML 2.3@
739 */
740
741int /* O - New reference count */
742mxmlRetain(mxml_node_t *node) /* I - Node */
743{
744 if (node)
745 return (++ node->ref_count);
746 else
747 return (-1);
748}
749
750
751/*
752 * 'mxml_new()' - Create a new node.
753 */
754
755static mxml_node_t * /* O - New node */
756mxml_new(mxml_node_t *parent, /* I - Parent node */
757 mxml_type_t type) /* I - Node type */
758{
759 mxml_node_t *node; /* New node */
760
761
762#if DEBUG > 1
763 fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
764#endif /* DEBUG > 1 */
765
766 /*
767 * Allocate memory for the node...
768 */
769
770 if ((node = calloc(1, sizeof(mxml_node_t))) == NULL)
771 {
772#if DEBUG > 1
773 fputs(" returning NULL\n", stderr);
774#endif /* DEBUG > 1 */
775
776 return (NULL);
777 }
778
779#if DEBUG > 1
780 fprintf(stderr, " returning %p\n", node);
781#endif /* DEBUG > 1 */
782
783 /*
784 * Set the node type...
785 */
786
787 node->type = type;
788 node->ref_count = 1;
789
790 /*
791 * Add to the parent if present...
792 */
793
794 if (parent)
795 mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
796
797 /*
798 * Return the new node...
799 */
800
801 return (node);
802}
803
804
805/*
806 * End of "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $".
807 */
diff --git a/pathologist/src/minixml/mxml-private.c b/pathologist/src/minixml/mxml-private.c
new file mode 100644
index 0000000..72f3e23
--- /dev/null
+++ b/pathologist/src/minixml/mxml-private.c
@@ -0,0 +1,331 @@
1/*
2 * "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $"
3 *
4 * Private functions for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxml_error() - Display an error message.
19 * mxml_integer_cb() - Default callback for integer values.
20 * mxml_opaque_cb() - Default callback for opaque values.
21 * mxml_real_cb() - Default callback for real number values.
22 * _mxml_global() - Get global data.
23 */
24
25/*
26 * Include necessary headers...
27 */
28
29#include "mxml-private.h"
30
31
32/*
33 * Some crazy people think that unloading a shared object is a good or safe
34 * thing to do. Unfortunately, most objects are simply *not* safe to unload
35 * and bad things *will* happen.
36 *
37 * The following mess of conditional code allows us to provide a destructor
38 * function in Mini-XML for our thread-global storage so that it can possibly
39 * be unloaded safely, although since there is no standard way to do so I
40 * can't even provide any guarantees that you can do it safely on all platforms.
41 *
42 * This code currently supports AIX, HP-UX, Linux, Mac OS X, Solaris, and
43 * Windows. It might work on the BSDs and IRIX, but I haven't tested that.
44 */
45
46#if defined(__sun) || defined(_AIX)
47# pragma fini(_mxml_fini)
48# define _MXML_FINI _mxml_fini
49#elif defined(__hpux)
50# pragma FINI _mxml_fini
51# define _MXML_FINI _mxml_fini
52#elif defined(__GNUC__) /* Linux and Mac OS X */
53# define _MXML_FINI __attribute((destructor)) _mxml_fini
54#else
55# define _MXML_FINI _fini
56#endif /* __sun */
57
58
59/*
60 * 'mxml_error()' - Display an error message.
61 */
62
63void
64mxml_error(const char *format, /* I - Printf-style format string */
65 ...) /* I - Additional arguments as needed */
66{
67 va_list ap; /* Pointer to arguments */
68 char s[1024]; /* Message string */
69 _mxml_global_t *global = _mxml_global();
70 /* Global data */
71
72
73 /*
74 * Range check input...
75 */
76
77 if (!format)
78 return;
79
80 /*
81 * Format the error message string...
82 */
83
84 va_start(ap, format);
85
86 vsnprintf(s, sizeof(s), format, ap);
87
88 va_end(ap);
89
90 /*
91 * And then display the error message...
92 */
93
94 if (global->error_cb)
95 (*global->error_cb)(s);
96 else
97 fprintf(stderr, "mxml: %s\n", s);
98}
99
100
101/*
102 * 'mxml_ignore_cb()' - Default callback for ignored values.
103 */
104
105mxml_type_t /* O - Node type */
106mxml_ignore_cb(mxml_node_t *node) /* I - Current node */
107{
108 (void)node;
109
110 return (MXML_IGNORE);
111}
112
113
114/*
115 * 'mxml_integer_cb()' - Default callback for integer values.
116 */
117
118mxml_type_t /* O - Node type */
119mxml_integer_cb(mxml_node_t *node) /* I - Current node */
120{
121 (void)node;
122
123 return (MXML_INTEGER);
124}
125
126
127/*
128 * 'mxml_opaque_cb()' - Default callback for opaque values.
129 */
130
131mxml_type_t /* O - Node type */
132mxml_opaque_cb(mxml_node_t *node) /* I - Current node */
133{
134 (void)node;
135
136 return (MXML_OPAQUE);
137}
138
139
140/*
141 * 'mxml_real_cb()' - Default callback for real number values.
142 */
143
144mxml_type_t /* O - Node type */
145mxml_real_cb(mxml_node_t *node) /* I - Current node */
146{
147 (void)node;
148
149 return (MXML_REAL);
150}
151
152
153#ifdef HAVE_PTHREAD_H /**** POSIX threading ****/
154# include <pthread.h>
155
156static pthread_key_t _mxml_key = -1; /* Thread local storage key */
157static pthread_once_t _mxml_key_once = PTHREAD_ONCE_INIT;
158 /* One-time initialization object */
159static void _mxml_init(void);
160static void _mxml_destructor(void *g);
161
162
163/*
164 * '_mxml_destructor()' - Free memory used for globals...
165 */
166
167static void
168_mxml_destructor(void *g) /* I - Global data */
169{
170 free(g);
171}
172
173
174/*
175 * '_mxml_fini()' - Clean up when unloaded.
176 */
177
178static void
179_MXML_FINI(void)
180{
181 _mxml_global_t *global; /* Global data */
182
183
184 if (_mxml_key != -1)
185 {
186 if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) != NULL)
187 _mxml_destructor(global);
188
189 pthread_key_delete(_mxml_key);
190 _mxml_key = -1;
191 }
192}
193
194
195/*
196 * '_mxml_global()' - Get global data.
197 */
198
199_mxml_global_t * /* O - Global data */
200_mxml_global(void)
201{
202 _mxml_global_t *global; /* Global data */
203
204
205 pthread_once(&_mxml_key_once, _mxml_init);
206
207 if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) == NULL)
208 {
209 global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
210 pthread_setspecific(_mxml_key, global);
211
212 global->num_entity_cbs = 1;
213 global->entity_cbs[0] = _mxml_entity_cb;
214 global->wrap = 72;
215 }
216
217 return (global);
218}
219
220
221/*
222 * '_mxml_init()' - Initialize global data...
223 */
224
225static void
226_mxml_init(void)
227{
228 pthread_key_create(&_mxml_key, _mxml_destructor);
229}
230
231
232#elif defined(WIN32) && defined(MXML1_EXPORTS) /**** WIN32 threading ****/
233# include <windows.h>
234
235static DWORD _mxml_tls_index; /* Index for global storage */
236
237
238/*
239 * 'DllMain()' - Main entry for library.
240 */
241
242BOOL WINAPI /* O - Success/failure */
243DllMain(HINSTANCE hinst, /* I - DLL module handle */
244 DWORD reason, /* I - Reason */
245 LPVOID reserved) /* I - Unused */
246{
247 _mxml_global_t *global; /* Global data */
248
249
250 (void)hinst;
251 (void)reserved;
252
253 switch (reason)
254 {
255 case DLL_PROCESS_ATTACH : /* Called on library initialization */
256 if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
257 return (FALSE);
258 break;
259
260 case DLL_THREAD_DETACH : /* Called when a thread terminates */
261 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
262 free(global);
263 break;
264
265 case DLL_PROCESS_DETACH : /* Called when library is unloaded */
266 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
267 free(global);
268
269 TlsFree(_mxml_tls_index);
270 break;
271
272 default:
273 break;
274 }
275
276 return (TRUE);
277}
278
279
280/*
281 * '_mxml_global()' - Get global data.
282 */
283
284_mxml_global_t * /* O - Global data */
285_mxml_global(void)
286{
287 _mxml_global_t *global; /* Global data */
288
289
290 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) == NULL)
291 {
292 global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
293
294 global->num_entity_cbs = 1;
295 global->entity_cbs[0] = _mxml_entity_cb;
296 global->wrap = 72;
297
298 TlsSetValue(_mxml_tls_index, (LPVOID)global);
299 }
300
301 return (global);
302}
303
304
305#else /**** No threading ****/
306/*
307 * '_mxml_global()' - Get global data.
308 */
309
310_mxml_global_t * /* O - Global data */
311_mxml_global(void)
312{
313 static _mxml_global_t global = /* Global data */
314 {
315 NULL, /* error_cb */
316 1, /* num_entity_cbs */
317 { _mxml_entity_cb }, /* entity_cbs */
318 72, /* wrap */
319 NULL, /* custom_load_cb */
320 NULL /* custom_save_cb */
321 };
322
323
324 return (&global);
325}
326#endif /* HAVE_PTHREAD_H */
327
328
329/*
330 * End of "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $".
331 */
diff --git a/pathologist/src/minixml/mxml-private.h b/pathologist/src/minixml/mxml-private.h
new file mode 100644
index 0000000..8789e6c
--- /dev/null
+++ b/pathologist/src/minixml/mxml-private.h
@@ -0,0 +1,50 @@
1/*
2 * "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $"
3 *
4 * Private definitions for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 */
16
17/*
18 * Include necessary headers...
19 */
20
21#include "config.h"
22#include "mxml.h"
23
24
25/*
26 * Global, per-thread data...
27 */
28
29typedef struct _mxml_global_s
30{
31 void (*error_cb)(const char *);
32 int num_entity_cbs;
33 int (*entity_cbs[100])(const char *name);
34 int wrap;
35 mxml_custom_load_cb_t custom_load_cb;
36 mxml_custom_save_cb_t custom_save_cb;
37} _mxml_global_t;
38
39
40/*
41 * Functions...
42 */
43
44extern _mxml_global_t *_mxml_global(void);
45extern int _mxml_entity_cb(const char *name);
46
47
48/*
49 * End of "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $".
50 */
diff --git a/pathologist/src/minixml/mxml-search.c b/pathologist/src/minixml/mxml-search.c
new file mode 100644
index 0000000..f975af1
--- /dev/null
+++ b/pathologist/src/minixml/mxml-search.c
@@ -0,0 +1,287 @@
1/*
2 * "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $"
3 *
4 * Search/navigation functions for Mini-XML, a small XML-like file
5 * parsing library.
6 *
7 * Copyright 2003-2010 by Michael R Sweet.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Michael R Sweet and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "COPYING"
12 * which should have been included with this file. If this file is
13 * missing or damaged, see the license at:
14 *
15 * http://www.minixml.org/
16 *
17 * Contents:
18 *
19 * mxmlFindElement() - Find the named element.
20 * mxmlFindValue() - Find a value with the given path.
21 * mxmlWalkNext() - Walk to the next logical node in the tree.
22 * mxmlWalkPrev() - Walk to the previous logical node in the tree.
23 */
24
25/*
26 * Include necessary headers...
27 */
28
29#include "config.h"
30#include "mxml.h"
31
32
33/*
34 * 'mxmlFindElement()' - Find the named element.
35 *
36 * The search is constrained by the name, attribute name, and value; any
37 * NULL names or values are treated as wildcards, so different kinds of
38 * searches can be implemented by looking for all elements of a given name
39 * or all elements with a specific attribute. The descend argument determines
40 * whether the search descends into child nodes; normally you will use
41 * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
42 * additional direct descendents of the node. The top node argument
43 * constrains the search to a particular node's children.
44 */
45
46mxml_node_t * /* O - Element node or NULL */
47mxmlFindElement(mxml_node_t *node, /* I - Current node */
48 mxml_node_t *top, /* I - Top node */
49 const char *name, /* I - Element name or NULL for any */
50 const char *attr, /* I - Attribute name, or NULL for none */
51 const char *value, /* I - Attribute value, or NULL for any */
52 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
53{
54 const char *temp; /* Current attribute value */
55
56
57 /*
58 * Range check input...
59 */
60
61 if (!node || !top || (!attr && value))
62 return (NULL);
63
64 /*
65 * Start with the next node...
66 */
67
68 node = mxmlWalkNext(node, top, descend);
69
70 /*
71 * Loop until we find a matching element...
72 */
73
74 while (node != NULL)
75 {
76 /*
77 * See if this node matches...
78 */
79
80 if (node->type == MXML_ELEMENT &&
81 node->value.element.name &&
82 (!name || !strcmp(node->value.element.name, name)))
83 {
84 /*
85 * See if we need to check for an attribute...
86 */
87
88 if (!attr)
89 return (node); /* No attribute search, return it... */
90
91 /*
92 * Check for the attribute...
93 */
94
95 if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
96 {
97 /*
98 * OK, we have the attribute, does it match?
99 */
100
101 if (!value || !strcmp(value, temp))
102 return (node); /* Yes, return it... */
103 }
104 }
105
106 /*
107 * No match, move on to the next node...
108 */
109
110 if (descend == MXML_DESCEND)
111 node = mxmlWalkNext(node, top, MXML_DESCEND);
112 else
113 node = node->next;
114 }
115
116 return (NULL);
117}
118
119
120/*
121 * 'mxmlFindPath()' - Find a node with the given path.
122 *
123 * The "path" is a slash-separated list of element names. The name "*" is
124 * considered a wildcard for one or more levels of elements. For example,
125 * "foo/one/two", "bar/two/one", "*\/one", and so forth.
126 *
127 * The first child node of the found node is returned if the given node has
128 * children and the first child is a value node.
129 *
130 * @since Mini-XML 2.7@
131 */
132
133mxml_node_t * /* O - Found node or NULL */
134mxmlFindPath(mxml_node_t *top, /* I - Top node */
135 const char *path) /* I - Path to element */
136{
137 mxml_node_t *node; /* Current node */
138 char element[256]; /* Current element name */
139 const char *pathsep; /* Separator in path */
140 int descend; /* mxmlFindElement option */
141
142
143 /*
144 * Range check input...
145 */
146
147 if (!top || !path || !*path)
148 return (NULL);
149
150 /*
151 * Search each element in the path...
152 */
153
154 node = top;
155 while (*path)
156 {
157 /*
158 * Handle wildcards...
159 */
160
161 if (!strncmp(path, "*/", 2))
162 {
163 path += 2;
164 descend = MXML_DESCEND;
165 }
166 else
167 descend = MXML_DESCEND_FIRST;
168
169 /*
170 * Get the next element in the path...
171 */
172
173 if ((pathsep = strchr(path, '/')) == NULL)
174 pathsep = path + strlen(path);
175
176 if (pathsep == path || (pathsep - path) >= sizeof(element))
177 return (NULL);
178
179 memcpy(element, path, pathsep - path);
180 element[pathsep - path] = '\0';
181
182 if (*pathsep)
183 path = pathsep + 1;
184 else
185 path = pathsep;
186
187 /*
188 * Search for the element...
189 */
190
191 if ((node = mxmlFindElement(node, node, element, NULL, NULL,
192 descend)) == NULL)
193 return (NULL);
194 }
195
196 /*
197 * If we get this far, return the node or its first child...
198 */
199
200 if (node->child && node->child->type != MXML_ELEMENT)
201 return (node->child);
202 else
203 return (node);
204}
205
206
207/*
208 * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
209 *
210 * The descend argument controls whether the first child is considered
211 * to be the next node. The top node argument constrains the walk to
212 * the node's children.
213 */
214
215mxml_node_t * /* O - Next node or NULL */
216mxmlWalkNext(mxml_node_t *node, /* I - Current node */
217 mxml_node_t *top, /* I - Top node */
218 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
219{
220 if (!node)
221 return (NULL);
222 else if (node->child && descend)
223 return (node->child);
224 else if (node == top)
225 return (NULL);
226 else if (node->next)
227 return (node->next);
228 else if (node->parent && node->parent != top)
229 {
230 node = node->parent;
231
232 while (!node->next)
233 if (node->parent == top || !node->parent)
234 return (NULL);
235 else
236 node = node->parent;
237
238 return (node->next);
239 }
240 else
241 return (NULL);
242}
243
244
245/*
246 * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
247 *
248 * The descend argument controls whether the previous node's last child
249 * is considered to be the previous node. The top node argument constrains
250 * the walk to the node's children.
251 */
252
253mxml_node_t * /* O - Previous node or NULL */
254mxmlWalkPrev(mxml_node_t *node, /* I - Current node */
255 mxml_node_t *top, /* I - Top node */
256 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
257{
258 if (!node || node == top)
259 return (NULL);
260 else if (node->prev)
261 {
262 if (node->prev->last_child && descend)
263 {
264 /*
265 * Find the last child under the previous node...
266 */
267
268 node = node->prev->last_child;
269
270 while (node->last_child)
271 node = node->last_child;
272
273 return (node);
274 }
275 else
276 return (node->prev);
277 }
278 else if (node->parent != top)
279 return (node->parent);
280 else
281 return (NULL);
282}
283
284
285/*
286 * End of "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $".
287 */
diff --git a/pathologist/src/minixml/mxml-set.c b/pathologist/src/minixml/mxml-set.c
new file mode 100644
index 0000000..b0bd527
--- /dev/null
+++ b/pathologist/src/minixml/mxml-set.c
@@ -0,0 +1,349 @@
1/*
2 * "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $"
3 *
4 * Node set functions for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2011 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlSetCDATA() - Set the element name of a CDATA node.
19 * mxmlSetCustom() - Set the data and destructor of a custom data node.
20 * mxmlSetElement() - Set the name of an element node.
21 * mxmlSetInteger() - Set the value of an integer node.
22 * mxmlSetOpaque() - Set the value of an opaque node.
23 * mxmlSetReal() - Set the value of a real number node.
24 * mxmlSetText() - Set the value of a text node.
25 * mxmlSetTextf() - Set the value of a text node to a formatted string.
26 * mxmlSetUserData() - Set the user data pointer for a node.
27 */
28
29/*
30 * Include necessary headers...
31 */
32
33#include "config.h"
34#include "mxml.h"
35
36
37/*
38 * 'mxmlSetCDATA()' - Set the element name of a CDATA node.
39 *
40 * The node is not changed if it (or its first child) is not a CDATA element node.
41 *
42 * @since Mini-XML 2.3@
43 */
44
45int /* O - 0 on success, -1 on failure */
46mxmlSetCDATA(mxml_node_t *node, /* I - Node to set */
47 const char *data) /* I - New data string */
48{
49 /*
50 * Range check input...
51 */
52
53 if (node && node->type == MXML_ELEMENT &&
54 strncmp(node->value.element.name, "![CDATA[", 8) &&
55 node->child && node->child->type == MXML_ELEMENT &&
56 !strncmp(node->child->value.element.name, "![CDATA[", 8))
57 node = node->child;
58
59 if (!node || node->type != MXML_ELEMENT || !data ||
60 strncmp(node->value.element.name, "![CDATA[", 8))
61 return (-1);
62
63 /*
64 * Free any old element value and set the new value...
65 */
66
67 if (node->value.element.name)
68 free(node->value.element.name);
69
70 node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
71
72 return (0);
73}
74
75
76/*
77 * 'mxmlSetCustom()' - Set the data and destructor of a custom data node.
78 *
79 * The node is not changed if it (or its first child) is not a custom node.
80 *
81 * @since Mini-XML 2.1@
82 */
83
84int /* O - 0 on success, -1 on failure */
85mxmlSetCustom(
86 mxml_node_t *node, /* I - Node to set */
87 void *data, /* I - New data pointer */
88 mxml_custom_destroy_cb_t destroy) /* I - New destructor function */
89{
90 /*
91 * Range check input...
92 */
93
94 if (node && node->type == MXML_ELEMENT &&
95 node->child && node->child->type == MXML_CUSTOM)
96 node = node->child;
97
98 if (!node || node->type != MXML_CUSTOM)
99 return (-1);
100
101 /*
102 * Free any old element value and set the new value...
103 */
104
105 if (node->value.custom.data && node->value.custom.destroy)
106 (*(node->value.custom.destroy))(node->value.custom.data);
107
108 node->value.custom.data = data;
109 node->value.custom.destroy = destroy;
110
111 return (0);
112}
113
114
115/*
116 * 'mxmlSetElement()' - Set the name of an element node.
117 *
118 * The node is not changed if it is not an element node.
119 */
120
121int /* O - 0 on success, -1 on failure */
122mxmlSetElement(mxml_node_t *node, /* I - Node to set */
123 const char *name) /* I - New name string */
124{
125 /*
126 * Range check input...
127 */
128
129 if (!node || node->type != MXML_ELEMENT || !name)
130 return (-1);
131
132 /*
133 * Free any old element value and set the new value...
134 */
135
136 if (node->value.element.name)
137 free(node->value.element.name);
138
139 node->value.element.name = strdup(name);
140
141 return (0);
142}
143
144
145/*
146 * 'mxmlSetInteger()' - Set the value of an integer node.
147 *
148 * The node is not changed if it (or its first child) is not an integer node.
149 */
150
151int /* O - 0 on success, -1 on failure */
152mxmlSetInteger(mxml_node_t *node, /* I - Node to set */
153 int integer) /* I - Integer value */
154{
155 /*
156 * Range check input...
157 */
158
159 if (node && node->type == MXML_ELEMENT &&
160 node->child && node->child->type == MXML_INTEGER)
161 node = node->child;
162
163 if (!node || node->type != MXML_INTEGER)
164 return (-1);
165
166 /*
167 * Set the new value and return...
168 */
169
170 node->value.integer = integer;
171
172 return (0);
173}
174
175
176/*
177 * 'mxmlSetOpaque()' - Set the value of an opaque node.
178 *
179 * The node is not changed if it (or its first child) is not an opaque node.
180 */
181
182int /* O - 0 on success, -1 on failure */
183mxmlSetOpaque(mxml_node_t *node, /* I - Node to set */
184 const char *opaque) /* I - Opaque string */
185{
186 /*
187 * Range check input...
188 */
189
190 if (node && node->type == MXML_ELEMENT &&
191 node->child && node->child->type == MXML_OPAQUE)
192 node = node->child;
193
194 if (!node || node->type != MXML_OPAQUE || !opaque)
195 return (-1);
196
197 /*
198 * Free any old opaque value and set the new value...
199 */
200
201 if (node->value.opaque)
202 free(node->value.opaque);
203
204 node->value.opaque = strdup(opaque);
205
206 return (0);
207}
208
209
210/*
211 * 'mxmlSetReal()' - Set the value of a real number node.
212 *
213 * The node is not changed if it (or its first child) is not a real number node.
214 */
215
216int /* O - 0 on success, -1 on failure */
217mxmlSetReal(mxml_node_t *node, /* I - Node to set */
218 double real) /* I - Real number value */
219{
220 /*
221 * Range check input...
222 */
223
224 if (node && node->type == MXML_ELEMENT &&
225 node->child && node->child->type == MXML_REAL)
226 node = node->child;
227
228 if (!node || node->type != MXML_REAL)
229 return (-1);
230
231 /*
232 * Set the new value and return...
233 */
234
235 node->value.real = real;
236
237 return (0);
238}
239
240
241/*
242 * 'mxmlSetText()' - Set the value of a text node.
243 *
244 * The node is not changed if it (or its first child) is not a text node.
245 */
246
247int /* O - 0 on success, -1 on failure */
248mxmlSetText(mxml_node_t *node, /* I - Node to set */
249 int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
250 const char *string) /* I - String */
251{
252 /*
253 * Range check input...
254 */
255
256 if (node && node->type == MXML_ELEMENT &&
257 node->child && node->child->type == MXML_TEXT)
258 node = node->child;
259
260 if (!node || node->type != MXML_TEXT || !string)
261 return (-1);
262
263 /*
264 * Free any old string value and set the new value...
265 */
266
267 if (node->value.text.string)
268 free(node->value.text.string);
269
270 node->value.text.whitespace = whitespace;
271 node->value.text.string = strdup(string);
272
273 return (0);
274}
275
276
277/*
278 * 'mxmlSetTextf()' - Set the value of a text node to a formatted string.
279 *
280 * The node is not changed if it (or its first child) is not a text node.
281 */
282
283int /* O - 0 on success, -1 on failure */
284mxmlSetTextf(mxml_node_t *node, /* I - Node to set */
285 int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
286 const char *format, /* I - Printf-style format string */
287 ...) /* I - Additional arguments as needed */
288{
289 va_list ap; /* Pointer to arguments */
290
291
292 /*
293 * Range check input...
294 */
295
296 if (node && node->type == MXML_ELEMENT &&
297 node->child && node->child->type == MXML_TEXT)
298 node = node->child;
299
300 if (!node || node->type != MXML_TEXT || !format)
301 return (-1);
302
303 /*
304 * Free any old string value and set the new value...
305 */
306
307 if (node->value.text.string)
308 free(node->value.text.string);
309
310 va_start(ap, format);
311
312 node->value.text.whitespace = whitespace;
313 node->value.text.string = _mxml_strdupf(format, ap);
314
315 va_end(ap);
316
317 return (0);
318}
319
320
321/*
322 * 'mxmlSetUserData()' - Set the user data pointer for a node.
323 *
324 * @since Mini-XML 2.7@
325 */
326
327int /* O - 0 on success, -1 on failure */
328mxmlSetUserData(mxml_node_t *node, /* I - Node to set */
329 void *data) /* I - User data pointer */
330{
331 /*
332 * Range check input...
333 */
334
335 if (!node)
336 return (-1);
337
338 /*
339 * Set the user data pointer and return...
340 */
341
342 node->user_data = data;
343 return (0);
344}
345
346
347/*
348 * End of "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $".
349 */
diff --git a/pathologist/src/minixml/mxml-string.c b/pathologist/src/minixml/mxml-string.c
new file mode 100644
index 0000000..6be4252
--- /dev/null
+++ b/pathologist/src/minixml/mxml-string.c
@@ -0,0 +1,476 @@
1/*
2 * "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $"
3 *
4 * String functions for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * _mxml_snprintf() - Format a string.
19 * _mxml_strdup() - Duplicate a string.
20 * _mxml_strdupf() - Format and duplicate a string.
21 * _mxml_vsnprintf() - Format a string into a fixed size buffer.
22 * _mxml_vstrdupf() - Format and duplicate a string.
23 */
24
25/*
26 * Include necessary headers...
27 */
28
29#include "config.h"
30
31
32/*
33 * The va_copy macro is part of C99, but many compilers don't implement it.
34 * Provide a "direct assignment" implmentation when va_copy isn't defined...
35 */
36
37#ifndef va_copy
38# ifdef __va_copy
39# define va_copy(dst,src) __va_copy(dst,src)
40# else
41# define va_copy(dst,src) memcpy(&dst, &src, sizeof(va_list))
42# endif /* __va_copy */
43#endif /* va_copy */
44
45
46#ifndef HAVE_SNPRINTF
47/*
48 * '_mxml_snprintf()' - Format a string.
49 */
50
51int /* O - Number of bytes formatted */
52_mxml_snprintf(char *buffer, /* I - Output buffer */
53 size_t bufsize, /* I - Size of output buffer */
54 const char *format, /* I - Printf-style format string */
55 ...) /* I - Additional arguments as needed */
56{
57 va_list ap; /* Argument list */
58 int bytes; /* Number of bytes formatted */
59
60
61 va_start(ap, format);
62 bytes = vsnprintf(buffer, bufsize, format, ap);
63 va_end(ap);
64
65 return (bytes);
66}
67#endif /* !HAVE_SNPRINTF */
68
69
70/*
71 * '_mxml_strdup()' - Duplicate a string.
72 */
73
74#ifndef HAVE_STRDUP
75char * /* O - New string pointer */
76_mxml_strdup(const char *s) /* I - String to duplicate */
77{
78 char *t; /* New string pointer */
79
80
81 if (s == NULL)
82 return (NULL);
83
84 if ((t = malloc(strlen(s) + 1)) == NULL)
85 return (NULL);
86
87 return (strcpy(t, s));
88}
89#endif /* !HAVE_STRDUP */
90
91
92/*
93 * '_mxml_strdupf()' - Format and duplicate a string.
94 */
95
96char * /* O - New string pointer */
97_mxml_strdupf(const char *format, /* I - Printf-style format string */
98 ...) /* I - Additional arguments as needed */
99{
100 va_list ap; /* Pointer to additional arguments */
101 char *s; /* Pointer to formatted string */
102
103
104 /*
105 * Get a pointer to the additional arguments, format the string,
106 * and return it...
107 */
108
109 va_start(ap, format);
110 s = _mxml_vstrdupf(format, ap);
111 va_end(ap);
112
113 return (s);
114}
115
116
117#ifndef HAVE_VSNPRINTF
118/*
119 * '_mxml_vsnprintf()' - Format a string into a fixed size buffer.
120 */
121
122int /* O - Number of bytes formatted */
123_mxml_vsnprintf(char *buffer, /* O - Output buffer */
124 size_t bufsize, /* O - Size of output buffer */
125 const char *format, /* I - Printf-style format string */
126 va_list ap) /* I - Pointer to additional arguments */
127{
128 char *bufptr, /* Pointer to position in buffer */
129 *bufend, /* Pointer to end of buffer */
130 sign, /* Sign of format width */
131 size, /* Size character (h, l, L) */
132 type; /* Format type character */
133 int width, /* Width of field */
134 prec; /* Number of characters of precision */
135 char tformat[100], /* Temporary format string for sprintf() */
136 *tptr, /* Pointer into temporary format */
137 temp[1024]; /* Buffer for formatted numbers */
138 char *s; /* Pointer to string */
139 int slen; /* Length of string */
140 int bytes; /* Total number of bytes needed */
141
142
143 /*
144 * Loop through the format string, formatting as needed...
145 */
146
147 bufptr = buffer;
148 bufend = buffer + bufsize - 1;
149 bytes = 0;
150
151 while (*format)
152 {
153 if (*format == '%')
154 {
155 tptr = tformat;
156 *tptr++ = *format++;
157
158 if (*format == '%')
159 {
160 if (bufptr && bufptr < bufend) *bufptr++ = *format;
161 bytes ++;
162 format ++;
163 continue;
164 }
165 else if (strchr(" -+#\'", *format))
166 {
167 *tptr++ = *format;
168 sign = *format++;
169 }
170 else
171 sign = 0;
172
173 if (*format == '*')
174 {
175 /*
176 * Get width from argument...
177 */
178
179 format ++;
180 width = va_arg(ap, int);
181
182 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
183 tptr += strlen(tptr);
184 }
185 else
186 {
187 width = 0;
188
189 while (isdigit(*format & 255))
190 {
191 if (tptr < (tformat + sizeof(tformat) - 1))
192 *tptr++ = *format;
193
194 width = width * 10 + *format++ - '0';
195 }
196 }
197
198 if (*format == '.')
199 {
200 if (tptr < (tformat + sizeof(tformat) - 1))
201 *tptr++ = *format;
202
203 format ++;
204
205 if (*format == '*')
206 {
207 /*
208 * Get precision from argument...
209 */
210
211 format ++;
212 prec = va_arg(ap, int);
213
214 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
215 tptr += strlen(tptr);
216 }
217 else
218 {
219 prec = 0;
220
221 while (isdigit(*format & 255))
222 {
223 if (tptr < (tformat + sizeof(tformat) - 1))
224 *tptr++ = *format;
225
226 prec = prec * 10 + *format++ - '0';
227 }
228 }
229 }
230 else
231 prec = -1;
232
233 if (*format == 'l' && format[1] == 'l')
234 {
235 size = 'L';
236
237 if (tptr < (tformat + sizeof(tformat) - 2))
238 {
239 *tptr++ = 'l';
240 *tptr++ = 'l';
241 }
242
243 format += 2;
244 }
245 else if (*format == 'h' || *format == 'l' || *format == 'L')
246 {
247 if (tptr < (tformat + sizeof(tformat) - 1))
248 *tptr++ = *format;
249
250 size = *format++;
251 }
252
253 if (!*format)
254 break;
255
256 if (tptr < (tformat + sizeof(tformat) - 1))
257 *tptr++ = *format;
258
259 type = *format++;
260 *tptr = '\0';
261
262 switch (type)
263 {
264 case 'E' : /* Floating point formats */
265 case 'G' :
266 case 'e' :
267 case 'f' :
268 case 'g' :
269 if ((width + 2) > sizeof(temp))
270 break;
271
272 sprintf(temp, tformat, va_arg(ap, double));
273
274 bytes += strlen(temp);
275
276 if (bufptr)
277 {
278 if ((bufptr + strlen(temp)) > bufend)
279 {
280 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
281 bufptr = bufend;
282 }
283 else
284 {
285 strcpy(bufptr, temp);
286 bufptr += strlen(temp);
287 }
288 }
289 break;
290
291 case 'B' : /* Integer formats */
292 case 'X' :
293 case 'b' :
294 case 'd' :
295 case 'i' :
296 case 'o' :
297 case 'u' :
298 case 'x' :
299 if ((width + 2) > sizeof(temp))
300 break;
301
302#ifdef HAVE_LONG_LONG
303 if (size == 'L')
304 sprintf(temp, tformat, va_arg(ap, long long));
305 else
306#endif /* HAVE_LONG_LONG */
307 sprintf(temp, tformat, va_arg(ap, int));
308
309 bytes += strlen(temp);
310
311 if (bufptr)
312 {
313 if ((bufptr + strlen(temp)) > bufend)
314 {
315 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
316 bufptr = bufend;
317 }
318 else
319 {
320 strcpy(bufptr, temp);
321 bufptr += strlen(temp);
322 }
323 }
324 break;
325
326 case 'p' : /* Pointer value */
327 if ((width + 2) > sizeof(temp))
328 break;
329
330 sprintf(temp, tformat, va_arg(ap, void *));
331
332 bytes += strlen(temp);
333
334 if (bufptr)
335 {
336 if ((bufptr + strlen(temp)) > bufend)
337 {
338 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
339 bufptr = bufend;
340 }
341 else
342 {
343 strcpy(bufptr, temp);
344 bufptr += strlen(temp);
345 }
346 }
347 break;
348
349 case 'c' : /* Character or character array */
350 bytes += width;
351
352 if (bufptr)
353 {
354 if (width <= 1)
355 *bufptr++ = va_arg(ap, int);
356 else
357 {
358 if ((bufptr + width) > bufend)
359 width = bufend - bufptr;
360
361 memcpy(bufptr, va_arg(ap, char *), (size_t)width);
362 bufptr += width;
363 }
364 }
365 break;
366
367 case 's' : /* String */
368 if ((s = va_arg(ap, char *)) == NULL)
369 s = "(null)";
370
371 slen = strlen(s);
372 if (slen > width && prec != width)
373 width = slen;
374
375 bytes += width;
376
377 if (bufptr)
378 {
379 if ((bufptr + width) > bufend)
380 width = bufend - bufptr;
381
382 if (slen > width)
383 slen = width;
384
385 if (sign == '-')
386 {
387 strncpy(bufptr, s, (size_t)slen);
388 memset(bufptr + slen, ' ', (size_t)(width - slen));
389 }
390 else
391 {
392 memset(bufptr, ' ', (size_t)(width - slen));
393 strncpy(bufptr + width - slen, s, (size_t)slen);
394 }
395
396 bufptr += width;
397 }
398 break;
399
400 case 'n' : /* Output number of chars so far */
401 *(va_arg(ap, int *)) = bytes;
402 break;
403 }
404 }
405 else
406 {
407 bytes ++;
408
409 if (bufptr && bufptr < bufend)
410 *bufptr++ = *format;
411
412 format ++;
413 }
414 }
415
416 /*
417 * Nul-terminate the string and return the number of characters needed.
418 */
419
420 *bufptr = '\0';
421
422 return (bytes);
423}
424#endif /* !HAVE_VSNPRINTF */
425
426
427/*
428 * '_mxml_vstrdupf()' - Format and duplicate a string.
429 */
430
431char * /* O - New string pointer */
432_mxml_vstrdupf(const char *format, /* I - Printf-style format string */
433 va_list ap) /* I - Pointer to additional arguments */
434{
435 int bytes; /* Number of bytes required */
436 char *buffer, /* String buffer */
437 temp[256]; /* Small buffer for first vsnprintf */
438 va_list apcopy; /* Copy of argument list */
439
440
441 /*
442 * First format with a tiny buffer; this will tell us how many bytes are
443 * needed...
444 */
445
446 va_copy(apcopy, ap);
447 bytes = vsnprintf(temp, sizeof(temp), format, apcopy);
448
449 if (bytes < sizeof(temp))
450 {
451 /*
452 * Hey, the formatted string fits in the tiny buffer, so just dup that...
453 */
454
455 return (strdup(temp));
456 }
457
458 /*
459 * Allocate memory for the whole thing and reformat to the new, larger
460 * buffer...
461 */
462
463 if ((buffer = calloc(1, bytes + 1)) != NULL)
464 vsnprintf(buffer, bytes + 1, format, ap);
465
466 /*
467 * Return the new string...
468 */
469
470 return (buffer);
471}
472
473
474/*
475 * End of "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $".
476 */
diff --git a/pathologist/src/minixml/mxmldoc.c b/pathologist/src/minixml/mxmldoc.c
new file mode 100644
index 0000000..28316ee
--- /dev/null
+++ b/pathologist/src/minixml/mxmldoc.c
@@ -0,0 +1,5809 @@
1/*#define DEBUG 1*/
2/*
3 * "$Id: mxmldoc.c 440 2011-08-11 18:51:26Z mike $"
4 *
5 * Documentation generator using Mini-XML, a small XML-like file parsing
6 * library.
7 *
8 * Copyright 2003-2011 by Michael R Sweet.
9 *
10 * These coded instructions, statements, and computer programs are the
11 * property of Michael R Sweet and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "COPYING"
13 * which should have been included with this file. If this file is
14 * missing or damaged, see the license at:
15 *
16 * http://www.minixml.org/
17 *
18 * Contents:
19 *
20 * main() - Main entry for test program.
21 * add_variable() - Add a variable or argument.
22 * find_public() - Find a public function, type, etc.
23 * get_comment_info() - Get info from comment.
24 * get_text() - Get the text for a node.
25 * load_cb() - Set the type of child nodes.
26 * new_documentation() - Create a new documentation tree.
27 * remove_directory() - Remove a directory.
28 * safe_strcpy() - Copy a string allowing for overlapping strings.
29 * scan_file() - Scan a source file.
30 * sort_node() - Insert a node sorted into a tree.
31 * update_comment() - Update a comment node.
32 * usage() - Show program usage...
33 * write_description() - Write the description text.
34 * write_element() - Write an element's text nodes.
35 * write_file() - Copy a file to the output.
36 * write_function() - Write documentation for a function.
37 * write_html() - Write HTML documentation.
38 * write_html_head() - Write the standard HTML header.
39 * write_man() - Write manpage documentation.
40 * write_scu() - Write a structure, class, or union.
41 * write_string() - Write a string, quoting HTML special chars as needed.
42 * write_toc() - Write a table-of-contents.
43 * write_tokens() - Write <Token> nodes for all APIs.
44 * ws_cb() - Whitespace callback for saving.
45 */
46
47/*
48 * Include necessary headers...
49 */
50
51#include "config.h"
52#include "mxml.h"
53#include <time.h>
54#include <sys/stat.h>
55#ifndef WIN32
56# include <dirent.h>
57# include <unistd.h>
58#endif /* !WIN32 */
59#ifdef __APPLE__
60# include <spawn.h>
61# include <sys/wait.h>
62extern char **environ;
63#endif /* __APPLE__ */
64
65
66/*
67 * This program scans source and header files and produces public API
68 * documentation for code that conforms to the CUPS Configuration
69 * Management Plan (CMP) coding standards. Please see the following web
70 * page for details:
71 *
72 * http://www.cups.org/cmp.html
73 *
74 * Using Mini-XML, this program creates and maintains an XML representation
75 * of the public API code documentation which can then be converted to HTML
76 * as desired. The following is a poor-man's schema:
77 *
78 * <?xml version="1.0"?>
79 * <mxmldoc xmlns="http://www.easysw.com"
80 * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
81 * xsi:schemaLocation="http://www.minixml.org/mxmldoc.xsd">
82 *
83 * <namespace name=""> [optional...]
84 * <constant name="">
85 * <description>descriptive text</description>
86 * </constant>
87 *
88 * <enumeration name="">
89 * <description>descriptive text</description>
90 * <constant name="">...</constant>
91 * </enumeration>
92 *
93 * <typedef name="">
94 * <description>descriptive text</description>
95 * <type>type string</type>
96 * </typedef>
97 *
98 * <function name="" scope="">
99 * <description>descriptive text</description>
100 * <argument name="" direction="I|O|IO" default="">
101 * <description>descriptive text</description>
102 * <type>type string</type>
103 * </argument>
104 * <returnvalue>
105 * <description>descriptive text</description>
106 * <type>type string</type>
107 * </returnvalue>
108 * <seealso>function names separated by spaces</seealso>
109 * </function>
110 *
111 * <variable name="" scope="">
112 * <description>descriptive text</description>
113 * <type>type string</type>
114 * </variable>
115 *
116 * <struct name="">
117 * <description>descriptive text</description>
118 * <variable name="">...</variable>
119 * <function name="">...</function>
120 * </struct>
121 *
122 * <union name="">
123 * <description>descriptive text</description>
124 * <variable name="">...</variable>
125 * </union>
126 *
127 * <class name="" parent="">
128 * <description>descriptive text</description>
129 * <class name="">...</class>
130 * <enumeration name="">...</enumeration>
131 * <function name="">...</function>
132 * <struct name="">...</struct>
133 * <variable name="">...</variable>
134 * </class>
135 * </namespace>
136 * </mxmldoc>
137 */
138
139
140/*
141 * Basic states for file parser...
142 */
143
144#define STATE_NONE 0 /* No state - whitespace, etc. */
145#define STATE_PREPROCESSOR 1 /* Preprocessor directive */
146#define STATE_C_COMMENT 2 /* Inside a C comment */
147#define STATE_CXX_COMMENT 3 /* Inside a C++ comment */
148#define STATE_STRING 4 /* Inside a string constant */
149#define STATE_CHARACTER 5 /* Inside a character constant */
150#define STATE_IDENTIFIER 6 /* Inside a keyword/identifier */
151
152
153/*
154 * Output modes...
155 */
156
157#define OUTPUT_NONE 0 /* No output */
158#define OUTPUT_HTML 1 /* Output HTML */
159#define OUTPUT_XML 2 /* Output XML */
160#define OUTPUT_MAN 3 /* Output nroff/man */
161#define OUTPUT_TOKENS 4 /* Output docset Tokens.xml file */
162
163
164/*
165 * Local functions...
166 */
167
168static mxml_node_t *add_variable(mxml_node_t *parent, const char *name,
169 mxml_node_t *type);
170static mxml_node_t *find_public(mxml_node_t *node, mxml_node_t *top,
171 const char *name);
172static char *get_comment_info(mxml_node_t *description);
173static char *get_text(mxml_node_t *node, char *buffer, int buflen);
174static mxml_type_t load_cb(mxml_node_t *node);
175static mxml_node_t *new_documentation(mxml_node_t **mxmldoc);
176static int remove_directory(const char *path);
177static void safe_strcpy(char *dst, const char *src);
178static int scan_file(const char *filename, FILE *fp,
179 mxml_node_t *doc);
180static void sort_node(mxml_node_t *tree, mxml_node_t *func);
181static void update_comment(mxml_node_t *parent,
182 mxml_node_t *comment);
183static void usage(const char *option);
184static void write_description(FILE *out, mxml_node_t *description,
185 const char *element, int summary);
186static void write_element(FILE *out, mxml_node_t *doc,
187 mxml_node_t *element, int mode);
188static void write_file(FILE *out, const char *file);
189static void write_function(FILE *out, mxml_node_t *doc,
190 mxml_node_t *function, int level);
191static void write_html(const char *section, const char *title,
192 const char *footerfile,
193 const char *headerfile,
194 const char *introfile, const char *cssfile,
195 const char *framefile,
196 const char *docset, const char *docversion,
197 const char *feedname, const char *feedurl,
198 mxml_node_t *doc);
199static void write_html_head(FILE *out, const char *section,
200 const char *title, const char *cssfile);
201static void write_man(const char *man_name, const char *section,
202 const char *title, const char *headerfile,
203 const char *footerfile, const char *introfile,
204 mxml_node_t *doc);
205static void write_scu(FILE *out, mxml_node_t *doc,
206 mxml_node_t *scut);
207static void write_string(FILE *out, const char *s, int mode);
208static void write_toc(FILE *out, mxml_node_t *doc,
209 const char *introfile, const char *target,
210 int xml);
211static void write_tokens(FILE *out, mxml_node_t *doc,
212 const char *path);
213static const char *ws_cb(mxml_node_t *node, int where);
214
215
216/*
217 * 'main()' - Main entry for test program.
218 */
219
220int /* O - Exit status */
221main(int argc, /* I - Number of command-line args */
222 char *argv[]) /* I - Command-line args */
223{
224 int i; /* Looping var */
225 int len; /* Length of argument */
226 FILE *fp; /* File to read */
227 mxml_node_t *doc; /* XML documentation tree */
228 mxml_node_t *mxmldoc; /* mxmldoc node */
229 const char *cssfile, /* CSS stylesheet file */
230 *docset, /* Documentation set directory */
231 *docversion, /* Documentation set version */
232 *feedname, /* Feed name for documentation set */
233 *feedurl, /* Feed URL for documentation set */
234 *footerfile, /* Footer file */
235 *framefile, /* Framed HTML basename */
236 *headerfile, /* Header file */
237 *introfile, /* Introduction file */
238 *name, /* Name of manpage */
239 *path, /* Path to help file for tokens */
240 *section, /* Section/keywords of documentation */
241 *title, /* Title of documentation */
242 *xmlfile; /* XML file */
243 int mode, /* Output mode */
244 update; /* Updated XML file */
245
246
247 /*
248 * Check arguments...
249 */
250
251 cssfile = NULL;
252 doc = NULL;
253 docset = NULL;
254 docversion = NULL;
255 feedname = NULL;
256 feedurl = NULL;
257 footerfile = NULL;
258 framefile = NULL;
259 headerfile = NULL;
260 introfile = NULL;
261 mode = OUTPUT_HTML;
262 mxmldoc = NULL;
263 name = NULL;
264 path = NULL;
265 section = NULL;
266 title = NULL;
267 update = 0;
268 xmlfile = NULL;
269
270 for (i = 1; i < argc; i ++)
271 if (!strcmp(argv[i], "--help"))
272 {
273 /*
274 * Show help...
275 */
276
277 usage(NULL);
278 }
279 else if (!strcmp(argv[i], "--version"))
280 {
281 /*
282 * Show version...
283 */
284
285 puts(MXML_VERSION + 10);
286 return (0);
287 }
288 else if (!strcmp(argv[i], "--css") && !cssfile)
289 {
290 /*
291 * Set CSS stylesheet file...
292 */
293
294 i ++;
295 if (i < argc)
296 cssfile = argv[i];
297 else
298 usage(NULL);
299 }
300 else if (!strcmp(argv[i], "--docset") && !docset)
301 {
302 /*
303 * Set documentation set directory...
304 */
305
306 i ++;
307 if (i < argc)
308 docset = argv[i];
309 else
310 usage(NULL);
311 }
312 else if (!strcmp(argv[i], "--docversion") && !docversion)
313 {
314 /*
315 * Set documentation set directory...
316 */
317
318 i ++;
319 if (i < argc)
320 docversion = argv[i];
321 else
322 usage(NULL);
323 }
324 else if (!strcmp(argv[i], "--footer") && !footerfile)
325 {
326 /*
327 * Set footer file...
328 */
329
330 i ++;
331 if (i < argc)
332 footerfile = argv[i];
333 else
334 usage(NULL);
335 }
336 else if (!strcmp(argv[i], "--feedname") && !feedname)
337 {
338 /*
339 * Set documentation set feed name...
340 */
341
342 i ++;
343 if (i < argc)
344 feedname = argv[i];
345 else
346 usage(NULL);
347 }
348 else if (!strcmp(argv[i], "--feedurl") && !feedurl)
349 {
350 /*
351 * Set documentation set feed name...
352 */
353
354 i ++;
355 if (i < argc)
356 feedurl = argv[i];
357 else
358 usage(NULL);
359 }
360 else if (!strcmp(argv[i], "--framed") && !framefile)
361 {
362 /*
363 * Set base filename for framed HTML output...
364 */
365
366 i ++;
367 if (i < argc)
368 framefile = argv[i];
369 else
370 usage(NULL);
371 }
372 else if (!strcmp(argv[i], "--header") && !headerfile)
373 {
374 /*
375 * Set header file...
376 */
377
378 i ++;
379 if (i < argc)
380 headerfile = argv[i];
381 else
382 usage(NULL);
383 }
384 else if (!strcmp(argv[i], "--intro") && !introfile)
385 {
386 /*
387 * Set intro file...
388 */
389
390 i ++;
391 if (i < argc)
392 introfile = argv[i];
393 else
394 usage(NULL);
395 }
396 else if (!strcmp(argv[i], "--man") && !name)
397 {
398 /*
399 * Output manpage...
400 */
401
402 i ++;
403 if (i < argc)
404 {
405 mode = OUTPUT_MAN;
406 name = argv[i];
407 }
408 else
409 usage(NULL);
410 }
411 else if (!strcmp(argv[i], "--no-output"))
412 mode = OUTPUT_NONE;
413 else if (!strcmp(argv[i], "--section") && !section)
414 {
415 /*
416 * Set section/keywords...
417 */
418
419 i ++;
420 if (i < argc)
421 section = argv[i];
422 else
423 usage(NULL);
424 }
425 else if (!strcmp(argv[i], "--title") && !title)
426 {
427 /*
428 * Set title...
429 */
430
431 i ++;
432 if (i < argc)
433 title = argv[i];
434 else
435 usage(NULL);
436 }
437 else if (!strcmp(argv[i], "--tokens"))
438 {
439 /*
440 * Output Tokens.xml file...
441 */
442
443 mode = OUTPUT_TOKENS;
444
445 i ++;
446 if (i < argc)
447 path = argv[i];
448 else
449 usage(NULL);
450 }
451 else if (argv[i][0] == '-')
452 {
453 /*
454 * Unknown/bad option...
455 */
456
457 usage(argv[i]);
458 }
459 else
460 {
461 /*
462 * Process XML or source file...
463 */
464
465 len = (int)strlen(argv[i]);
466 if (len > 4 && !strcmp(argv[i] + len - 4, ".xml"))
467 {
468 /*
469 * Set XML file...
470 */
471
472 if (xmlfile)
473 usage(NULL);
474
475 xmlfile = argv[i];
476
477 if (!doc)
478 {
479 if ((fp = fopen(argv[i], "r")) != NULL)
480 {
481 /*
482 * Read the existing XML file...
483 */
484
485 doc = mxmlLoadFile(NULL, fp, load_cb);
486
487 fclose(fp);
488
489 if (!doc)
490 {
491 mxmldoc = NULL;
492
493 fprintf(stderr,
494 "mxmldoc: Unable to read the XML documentation file "
495 "\"%s\"!\n", argv[i]);
496 }
497 else if ((mxmldoc = mxmlFindElement(doc, doc, "mxmldoc", NULL,
498 NULL, MXML_DESCEND)) == NULL)
499 {
500 fprintf(stderr,
501 "mxmldoc: XML documentation file \"%s\" is missing "
502 "<mxmldoc> node!!\n", argv[i]);
503
504 mxmlDelete(doc);
505 doc = NULL;
506 }
507 }
508 else
509 {
510 doc = NULL;
511 mxmldoc = NULL;
512 }
513
514 if (!doc)
515 doc = new_documentation(&mxmldoc);
516 }
517 }
518 else
519 {
520 /*
521 * Load source file...
522 */
523
524 update = 1;
525
526 if (!doc)
527 doc = new_documentation(&mxmldoc);
528
529 if ((fp = fopen(argv[i], "r")) == NULL)
530 {
531 fprintf(stderr, "mxmldoc: Unable to open source file \"%s\": %s\n",
532 argv[i], strerror(errno));
533 mxmlDelete(doc);
534 return (1);
535 }
536 else if (scan_file(argv[i], fp, mxmldoc))
537 {
538 fclose(fp);
539 mxmlDelete(doc);
540 return (1);
541 }
542 else
543 fclose(fp);
544 }
545 }
546
547 if (update && xmlfile)
548 {
549 /*
550 * Save the updated XML documentation file...
551 */
552
553 if ((fp = fopen(xmlfile, "w")) != NULL)
554 {
555 /*
556 * Write over the existing XML file...
557 */
558
559 mxmlSetWrapMargin(0);
560
561 if (mxmlSaveFile(doc, fp, ws_cb))
562 {
563 fprintf(stderr,
564 "mxmldoc: Unable to write the XML documentation file \"%s\": "
565 "%s!\n", xmlfile, strerror(errno));
566 fclose(fp);
567 mxmlDelete(doc);
568 return (1);
569 }
570
571 fclose(fp);
572 }
573 else
574 {
575 fprintf(stderr,
576 "mxmldoc: Unable to create the XML documentation file \"%s\": "
577 "%s!\n", xmlfile, strerror(errno));
578 mxmlDelete(doc);
579 return (1);
580 }
581 }
582
583 switch (mode)
584 {
585 case OUTPUT_HTML :
586 /*
587 * Write HTML documentation...
588 */
589
590 write_html(section, title ? title : "Documentation", footerfile,
591 headerfile, introfile, cssfile, framefile, docset,
592 docversion, feedname, feedurl, mxmldoc);
593 break;
594
595 case OUTPUT_MAN :
596 /*
597 * Write manpage documentation...
598 */
599
600 write_man(name, section, title, footerfile, headerfile, introfile,
601 mxmldoc);
602 break;
603
604 case OUTPUT_TOKENS :
605 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
606 "<Tokens version=\"1.0\">\n", stdout);
607
608 write_tokens(stdout, mxmldoc, path);
609
610 fputs("</Tokens>\n", stdout);
611 break;
612 }
613
614 /*
615 * Delete the tree and return...
616 */
617
618 mxmlDelete(doc);
619
620 return (0);
621}
622
623
624/*
625 * 'add_variable()' - Add a variable or argument.
626 */
627
628static mxml_node_t * /* O - New variable/argument */
629add_variable(mxml_node_t *parent, /* I - Parent node */
630 const char *name, /* I - "argument" or "variable" */
631 mxml_node_t *type) /* I - Type nodes */
632{
633 mxml_node_t *variable, /* New variable */
634 *node, /* Current node */
635 *next; /* Next node */
636 char buffer[16384], /* String buffer */
637 *bufptr; /* Pointer into buffer */
638
639
640#ifdef DEBUG
641 fprintf(stderr, "add_variable(parent=%p, name=\"%s\", type=%p)\n",
642 parent, name, type);
643#endif /* DEBUG */
644
645 /*
646 * Range check input...
647 */
648
649 if (!type || !type->child)
650 return (NULL);
651
652 /*
653 * Create the variable/argument node...
654 */
655
656 variable = mxmlNewElement(parent, name);
657
658 /*
659 * Check for a default value...
660 */
661
662 for (node = type->child; node; node = node->next)
663 if (!strcmp(node->value.text.string, "="))
664 break;
665
666 if (node)
667 {
668 /*
669 * Default value found, copy it and add as a "default" attribute...
670 */
671
672 for (bufptr = buffer; node; bufptr += strlen(bufptr))
673 {
674 if (node->value.text.whitespace && bufptr > buffer)
675 *bufptr++ = ' ';
676
677 strcpy(bufptr, node->value.text.string);
678
679 next = node->next;
680 mxmlDelete(node);
681 node = next;
682 }
683
684 mxmlElementSetAttr(variable, "default", buffer);
685 }
686
687 /*
688 * Extract the argument/variable name...
689 */
690
691 if (type->last_child->value.text.string[0] == ')')
692 {
693 /*
694 * Handle "type (*name)(args)"...
695 */
696
697 for (node = type->child; node; node = node->next)
698 if (node->value.text.string[0] == '(')
699 break;
700
701 for (bufptr = buffer; node; bufptr += strlen(bufptr))
702 {
703 if (node->value.text.whitespace && bufptr > buffer)
704 *bufptr++ = ' ';
705
706 strcpy(bufptr, node->value.text.string);
707
708 next = node->next;
709 mxmlDelete(node);
710 node = next;
711 }
712 }
713 else
714 {
715 /*
716 * Handle "type name"...
717 */
718
719 strcpy(buffer, type->last_child->value.text.string);
720 mxmlDelete(type->last_child);
721 }
722
723 /*
724 * Set the name...
725 */
726
727 mxmlElementSetAttr(variable, "name", buffer);
728
729 /*
730 * Add the remaining type information to the variable node...
731 */
732
733 mxmlAdd(variable, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
734
735 /*
736 * Add new new variable node...
737 */
738
739 return (variable);
740}
741
742
743/*
744 * 'find_public()' - Find a public function, type, etc.
745 */
746
747static mxml_node_t * /* I - Found node or NULL */
748find_public(mxml_node_t *node, /* I - Current node */
749 mxml_node_t *top, /* I - Top node */
750 const char *name) /* I - Name of element */
751{
752 mxml_node_t *description, /* Description node */
753 *comment; /* Comment node */
754
755
756 for (node = mxmlFindElement(node, top, name, NULL, NULL,
757 node == top ? MXML_DESCEND_FIRST :
758 MXML_NO_DESCEND);
759 node;
760 node = mxmlFindElement(node, top, name, NULL, NULL, MXML_NO_DESCEND))
761 {
762 /*
763 * Get the description for this node...
764 */
765
766 description = mxmlFindElement(node, node, "description", NULL, NULL,
767 MXML_DESCEND_FIRST);
768
769 /*
770 * A missing or empty description signals a private node...
771 */
772
773 if (!description)
774 continue;
775
776 /*
777 * Look for @private@ in the comment text...
778 */
779
780 for (comment = description->child; comment; comment = comment->next)
781 if ((comment->type == MXML_TEXT &&
782 strstr(comment->value.text.string, "@private@")) ||
783 (comment->type == MXML_OPAQUE &&
784 strstr(comment->value.opaque, "@private@")))
785 break;
786
787 if (!comment)
788 {
789 /*
790 * No @private@, so return this node...
791 */
792
793 return (node);
794 }
795 }
796
797 /*
798 * If we get here, there are no (more) public nodes...
799 */
800
801 return (NULL);
802}
803
804
805/*
806 * 'get_comment_info()' - Get info from comment.
807 */
808
809static char * /* O - Info from comment */
810get_comment_info(
811 mxml_node_t *description) /* I - Description node */
812{
813 char text[10240], /* Description text */
814 since[255], /* @since value */
815 *ptr; /* Pointer into text */
816 static char info[1024]; /* Info string */
817
818
819 if (!description)
820 return ("");
821
822 get_text(description, text, sizeof(text));
823
824 for (ptr = strchr(text, '@'); ptr; ptr = strchr(ptr + 1, '@'))
825 {
826 if (!strncmp(ptr, "@deprecated@", 12))
827 return ("<span class=\"info\">&nbsp;DEPRECATED&nbsp;</span>");
828 else if (!strncmp(ptr, "@since ", 7))
829 {
830 strncpy(since, ptr + 7, sizeof(since) - 1);
831 since[sizeof(since) - 1] = '\0';
832
833 if ((ptr = strchr(since, '@')) != NULL)
834 *ptr = '\0';
835
836 snprintf(info, sizeof(info), "<span class=\"info\">&nbsp;%s&nbsp;</span>", since);
837 return (info);
838 }
839 }
840
841 return ("");
842}
843
844
845/*
846 * 'get_text()' - Get the text for a node.
847 */
848
849static char * /* O - Text in node */
850get_text(mxml_node_t *node, /* I - Node to get */
851 char *buffer, /* I - Buffer */
852 int buflen) /* I - Size of buffer */
853{
854 char *ptr, /* Pointer into buffer */
855 *end; /* End of buffer */
856 int len; /* Length of node */
857 mxml_node_t *current; /* Current node */
858
859
860 ptr = buffer;
861 end = buffer + buflen - 1;
862
863 for (current = node->child; current && ptr < end; current = current->next)
864 {
865 if (current->type == MXML_TEXT)
866 {
867 if (current->value.text.whitespace)
868 *ptr++ = ' ';
869
870 len = (int)strlen(current->value.text.string);
871 if (len > (int)(end - ptr))
872 len = (int)(end - ptr);
873
874 memcpy(ptr, current->value.text.string, len);
875 ptr += len;
876 }
877 else if (current->type == MXML_OPAQUE)
878 {
879 len = (int)strlen(current->value.opaque);
880 if (len > (int)(end - ptr))
881 len = (int)(end - ptr);
882
883 memcpy(ptr, current->value.opaque, len);
884 ptr += len;
885 }
886 }
887
888 *ptr = '\0';
889
890 return (buffer);
891}
892
893
894/*
895 * 'load_cb()' - Set the type of child nodes.
896 */
897
898static mxml_type_t /* O - Node type */
899load_cb(mxml_node_t *node) /* I - Node */
900{
901 if (!strcmp(node->value.element.name, "description"))
902 return (MXML_OPAQUE);
903 else
904 return (MXML_TEXT);
905}
906
907
908/*
909 * 'new_documentation()' - Create a new documentation tree.
910 */
911
912static mxml_node_t * /* O - New documentation */
913new_documentation(mxml_node_t **mxmldoc)/* O - mxmldoc node */
914{
915 mxml_node_t *doc; /* New documentation */
916
917
918 /*
919 * Create an empty XML documentation file...
920 */
921
922 doc = mxmlNewXML(NULL);
923
924 *mxmldoc = mxmlNewElement(doc, "mxmldoc");
925
926 mxmlElementSetAttr(*mxmldoc, "xmlns", "http://www.easysw.com");
927 mxmlElementSetAttr(*mxmldoc, "xmlns:xsi",
928 "http://www.w3.org/2001/XMLSchema-instance");
929 mxmlElementSetAttr(*mxmldoc, "xsi:schemaLocation",
930 "http://www.minixml.org/mxmldoc.xsd");
931
932 return (doc);
933}
934
935
936/*
937 * 'remove_directory()' - Remove a directory.
938 */
939
940static int /* O - 1 on success, 0 on failure */
941remove_directory(const char *path) /* I - Directory to remove */
942{
943#ifdef WIN32
944 /* TODO: Add Windows directory removal code */
945
946#else
947 DIR *dir; /* Directory */
948 struct dirent *dent; /* Current directory entry */
949 char filename[1024]; /* Current filename */
950 struct stat fileinfo; /* File information */
951
952
953 if ((dir = opendir(path)) == NULL)
954 {
955 fprintf(stderr, "mxmldoc: Unable to open directory \"%s\": %s\n", path,
956 strerror(errno));
957 return (0);
958 }
959
960 while ((dent = readdir(dir)) != NULL)
961 {
962 /*
963 * Skip "." and ".."...
964 */
965
966 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
967 continue;
968
969 /*
970 * See if we have a file or directory...
971 */
972
973 snprintf(filename, sizeof(filename), "%s/%s", path, dent->d_name);
974
975 if (stat(filename, &fileinfo))
976 {
977 fprintf(stderr, "mxmldoc: Unable to stat \"%s\": %s\n", filename,
978 strerror(errno));
979 closedir(dir);
980 return (0);
981 }
982
983 if (S_ISDIR(fileinfo.st_mode))
984 {
985 if (!remove_directory(filename))
986 {
987 closedir(dir);
988 return (0);
989 }
990 }
991 else if (unlink(filename))
992 {
993 fprintf(stderr, "mxmldoc: Unable to remove \"%s\": %s\n", filename,
994 strerror(errno));
995 closedir(dir);
996 return (0);
997 }
998 }
999
1000 closedir(dir);
1001
1002 if (rmdir(path))
1003 {
1004 fprintf(stderr, "mxmldoc: Unable to remove directory \"%s\": %s\n", path,
1005 strerror(errno));
1006 return (0);
1007 }
1008#endif /* WIN32 */
1009
1010 return (1);
1011}
1012
1013
1014/*
1015 * 'safe_strcpy()' - Copy a string allowing for overlapping strings.
1016 */
1017
1018static void
1019safe_strcpy(char *dst, /* I - Destination string */
1020 const char *src) /* I - Source string */
1021{
1022 while (*src)
1023 *dst++ = *src++;
1024
1025 *dst = '\0';
1026}
1027
1028
1029/*
1030 * 'scan_file()' - Scan a source file.
1031 */
1032
1033static int /* O - 0 on success, -1 on error */
1034scan_file(const char *filename, /* I - Filename */
1035 FILE *fp, /* I - File to scan */
1036 mxml_node_t *tree) /* I - Function tree */
1037{
1038 int state, /* Current parser state */
1039 braces, /* Number of braces active */
1040 parens; /* Number of active parenthesis */
1041 int ch; /* Current character */
1042 char buffer[65536], /* String buffer */
1043 *bufptr; /* Pointer into buffer */
1044 const char *scope; /* Current variable/function scope */
1045 mxml_node_t *comment, /* <comment> node */
1046 *constant, /* <constant> node */
1047 *enumeration, /* <enumeration> node */
1048 *function, /* <function> node */
1049 *fstructclass, /* function struct/class node */
1050 *structclass, /* <struct> or <class> node */
1051 *typedefnode, /* <typedef> node */
1052 *variable, /* <variable> or <argument> node */
1053 *returnvalue, /* <returnvalue> node */
1054 *type, /* <type> node */
1055 *description, /* <description> node */
1056 *node, /* Current node */
1057 *next; /* Next node */
1058#if DEBUG > 1
1059 mxml_node_t *temp; /* Temporary node */
1060 int oldstate, /* Previous state */
1061 oldch; /* Old character */
1062 static const char *states[] = /* State strings */
1063 {
1064 "STATE_NONE",
1065 "STATE_PREPROCESSOR",
1066 "STATE_C_COMMENT",
1067 "STATE_CXX_COMMENT",
1068 "STATE_STRING",
1069 "STATE_CHARACTER",
1070 "STATE_IDENTIFIER"
1071 };
1072#endif /* DEBUG > 1 */
1073
1074
1075#ifdef DEBUG
1076 fprintf(stderr, "scan_file(filename=\"%s\", fp=%p, tree=%p)\n", filename,
1077 fp, tree);
1078#endif /* DEBUG */
1079
1080 /*
1081 * Initialize the finite state machine...
1082 */
1083
1084 state = STATE_NONE;
1085 braces = 0;
1086 parens = 0;
1087 bufptr = buffer;
1088
1089 comment = mxmlNewElement(MXML_NO_PARENT, "temp");
1090 constant = NULL;
1091 enumeration = NULL;
1092 function = NULL;
1093 variable = NULL;
1094 returnvalue = NULL;
1095 type = NULL;
1096 description = NULL;
1097 typedefnode = NULL;
1098 structclass = NULL;
1099 fstructclass = NULL;
1100
1101 if (!strcmp(tree->value.element.name, "class"))
1102 scope = "private";
1103 else
1104 scope = NULL;
1105
1106 /*
1107 * Read until end-of-file...
1108 */
1109
1110 while ((ch = getc(fp)) != EOF)
1111 {
1112#if DEBUG > 1
1113 oldstate = state;
1114 oldch = ch;
1115#endif /* DEBUG > 1 */
1116
1117 switch (state)
1118 {
1119 case STATE_NONE : /* No state - whitespace, etc. */
1120 switch (ch)
1121 {
1122 case '/' : /* Possible C/C++ comment */
1123 ch = getc(fp);
1124 bufptr = buffer;
1125
1126 if (ch == '*')
1127 state = STATE_C_COMMENT;
1128 else if (ch == '/')
1129 state = STATE_CXX_COMMENT;
1130 else
1131 {
1132 ungetc(ch, fp);
1133
1134 if (type)
1135 {
1136#ifdef DEBUG
1137 fputs("Identifier: <<<< / >>>\n", stderr);
1138#endif /* DEBUG */
1139 ch = type->last_child->value.text.string[0];
1140 mxmlNewText(type, isalnum(ch) || ch == '_', "/");
1141 }
1142 }
1143 break;
1144
1145 case '#' : /* Preprocessor */
1146#ifdef DEBUG
1147 fputs(" #preprocessor...\n", stderr);
1148#endif /* DEBUG */
1149 state = STATE_PREPROCESSOR;
1150 break;
1151
1152 case '\'' : /* Character constant */
1153 state = STATE_CHARACTER;
1154 bufptr = buffer;
1155 *bufptr++ = ch;
1156 break;
1157
1158 case '\"' : /* String constant */
1159 state = STATE_STRING;
1160 bufptr = buffer;
1161 *bufptr++ = ch;
1162 break;
1163
1164 case '{' :
1165#ifdef DEBUG
1166 fprintf(stderr, " open brace, function=%p, type=%p...\n",
1167 function, type);
1168 if (type)
1169 fprintf(stderr, " type->child=\"%s\"...\n",
1170 type->child->value.text.string);
1171#endif /* DEBUG */
1172
1173 if (function)
1174 {
1175 if (fstructclass)
1176 {
1177 sort_node(fstructclass, function);
1178 fstructclass = NULL;
1179 }
1180 else
1181 sort_node(tree, function);
1182
1183 function = NULL;
1184 }
1185 else if (type && type->child &&
1186 ((!strcmp(type->child->value.text.string, "typedef") &&
1187 type->child->next &&
1188 (!strcmp(type->child->next->value.text.string, "struct") ||
1189 !strcmp(type->child->next->value.text.string, "union") ||
1190 !strcmp(type->child->next->value.text.string, "class"))) ||
1191 !strcmp(type->child->value.text.string, "union") ||
1192 !strcmp(type->child->value.text.string, "struct") ||
1193 !strcmp(type->child->value.text.string, "class")))
1194 {
1195 /*
1196 * Start of a class or structure...
1197 */
1198
1199 if (!strcmp(type->child->value.text.string, "typedef"))
1200 {
1201#ifdef DEBUG
1202 fputs(" starting typedef...\n", stderr);
1203#endif /* DEBUG */
1204
1205 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
1206 mxmlDelete(type->child);
1207 }
1208 else
1209 typedefnode = NULL;
1210
1211 structclass = mxmlNewElement(MXML_NO_PARENT,
1212 type->child->value.text.string);
1213
1214#ifdef DEBUG
1215 fprintf(stderr, "%c%s: <<<< %s >>>\n",
1216 toupper(type->child->value.text.string[0]),
1217 type->child->value.text.string + 1,
1218 type->child->next ?
1219 type->child->next->value.text.string : "(noname)");
1220
1221 fputs(" type =", stderr);
1222 for (node = type->child; node; node = node->next)
1223 fprintf(stderr, " \"%s\"", node->value.text.string);
1224 putc('\n', stderr);
1225
1226 fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
1227#endif /* DEBUG */
1228
1229 if (type->child->next)
1230 {
1231 mxmlElementSetAttr(structclass, "name",
1232 type->child->next->value.text.string);
1233 sort_node(tree, structclass);
1234 }
1235
1236 if (typedefnode && type->child)
1237 type->child->value.text.whitespace = 0;
1238 else if (structclass && type->child &&
1239 type->child->next && type->child->next->next)
1240 {
1241 for (bufptr = buffer, node = type->child->next->next;
1242 node;
1243 bufptr += strlen(bufptr))
1244 {
1245 if (node->value.text.whitespace && bufptr > buffer)
1246 *bufptr++ = ' ';
1247
1248 strcpy(bufptr, node->value.text.string);
1249
1250 next = node->next;
1251 mxmlDelete(node);
1252 node = next;
1253 }
1254
1255 mxmlElementSetAttr(structclass, "parent", buffer);
1256
1257 mxmlDelete(type);
1258 type = NULL;
1259 }
1260 else
1261 {
1262 mxmlDelete(type);
1263 type = NULL;
1264 }
1265
1266 if (typedefnode && comment->last_child)
1267 {
1268 /*
1269 * Copy comment for typedef as well as class/struct/union...
1270 */
1271
1272 mxmlNewText(comment, 0,
1273 comment->last_child->value.text.string);
1274 description = mxmlNewElement(typedefnode, "description");
1275#ifdef DEBUG
1276 fprintf(stderr,
1277 " duplicating comment %p/%p for typedef...\n",
1278 comment->last_child, comment->child);
1279#endif /* DEBUG */
1280 update_comment(typedefnode, comment->last_child);
1281 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
1282 comment->last_child);
1283 }
1284
1285 description = mxmlNewElement(structclass, "description");
1286#ifdef DEBUG
1287 fprintf(stderr, " adding comment %p/%p to %s...\n",
1288 comment->last_child, comment->child,
1289 structclass->value.element.name);
1290#endif /* DEBUG */
1291 update_comment(structclass, comment->last_child);
1292 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
1293 comment->last_child);
1294
1295 if (scan_file(filename, fp, structclass))
1296 {
1297 mxmlDelete(comment);
1298 return (-1);
1299 }
1300
1301#ifdef DEBUG
1302 fputs(" ended typedef...\n", stderr);
1303#endif /* DEBUG */
1304 structclass = NULL;
1305 break;
1306 }
1307 else if (type && type->child && type->child->next &&
1308 (!strcmp(type->child->value.text.string, "enum") ||
1309 (!strcmp(type->child->value.text.string, "typedef") &&
1310 !strcmp(type->child->next->value.text.string, "enum"))))
1311 {
1312 /*
1313 * Enumeration type...
1314 */
1315
1316 if (!strcmp(type->child->value.text.string, "typedef"))
1317 {
1318#ifdef DEBUG
1319 fputs(" starting typedef...\n", stderr);
1320#endif /* DEBUG */
1321
1322 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
1323 mxmlDelete(type->child);
1324 }
1325 else
1326 typedefnode = NULL;
1327
1328 enumeration = mxmlNewElement(MXML_NO_PARENT, "enumeration");
1329
1330#ifdef DEBUG
1331 fprintf(stderr, "Enumeration: <<<< %s >>>\n",
1332 type->child->next ?
1333 type->child->next->value.text.string : "(noname)");
1334#endif /* DEBUG */
1335
1336 if (type->child->next)
1337 {
1338 mxmlElementSetAttr(enumeration, "name",
1339 type->child->next->value.text.string);
1340 sort_node(tree, enumeration);
1341 }
1342
1343 if (typedefnode && type->child)
1344 type->child->value.text.whitespace = 0;
1345 else
1346 {
1347 mxmlDelete(type);
1348 type = NULL;
1349 }
1350
1351 if (typedefnode && comment->last_child)
1352 {
1353 /*
1354 * Copy comment for typedef as well as class/struct/union...
1355 */
1356
1357 mxmlNewText(comment, 0,
1358 comment->last_child->value.text.string);
1359 description = mxmlNewElement(typedefnode, "description");
1360#ifdef DEBUG
1361 fprintf(stderr,
1362 " duplicating comment %p/%p for typedef...\n",
1363 comment->last_child, comment->child);
1364#endif /* DEBUG */
1365 update_comment(typedefnode, comment->last_child);
1366 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
1367 comment->last_child);
1368 }
1369
1370 description = mxmlNewElement(enumeration, "description");
1371#ifdef DEBUG
1372 fprintf(stderr, " adding comment %p/%p to enumeration...\n",
1373 comment->last_child, comment->child);
1374#endif /* DEBUG */
1375 update_comment(enumeration, comment->last_child);
1376 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
1377 comment->last_child);
1378 }
1379 else if (type && type->child &&
1380 !strcmp(type->child->value.text.string, "extern"))
1381 {
1382 if (scan_file(filename, fp, tree))
1383 {
1384 mxmlDelete(comment);
1385 return (-1);
1386 }
1387 }
1388 else if (type)
1389 {
1390 mxmlDelete(type);
1391 type = NULL;
1392 }
1393
1394 braces ++;
1395 function = NULL;
1396 variable = NULL;
1397 break;
1398
1399 case '}' :
1400#ifdef DEBUG
1401 fputs(" close brace...\n", stderr);
1402#endif /* DEBUG */
1403
1404 if (structclass)
1405 scope = NULL;
1406
1407 if (!typedefnode)
1408 enumeration = NULL;
1409
1410 constant = NULL;
1411 structclass = NULL;
1412
1413 if (braces > 0)
1414 braces --;
1415 else
1416 {
1417 mxmlDelete(comment);
1418 return (0);
1419 }
1420 break;
1421
1422 case '(' :
1423 if (type)
1424 {
1425#ifdef DEBUG
1426 fputs("Identifier: <<<< ( >>>\n", stderr);
1427#endif /* DEBUG */
1428 mxmlNewText(type, 0, "(");
1429 }
1430
1431 parens ++;
1432 break;
1433
1434 case ')' :
1435 if (type && parens)
1436 {
1437#ifdef DEBUG
1438 fputs("Identifier: <<<< ) >>>\n", stderr);
1439#endif /* DEBUG */
1440 mxmlNewText(type, 0, ")");
1441 }
1442
1443 if (function && type && !parens)
1444 {
1445 /*
1446 * Check for "void" argument...
1447 */
1448
1449 if (type->child && type->child->next)
1450 variable = add_variable(function, "argument", type);
1451 else
1452 mxmlDelete(type);
1453
1454 type = NULL;
1455 }
1456
1457 if (parens > 0)
1458 parens --;
1459 break;
1460
1461 case ';' :
1462#ifdef DEBUG
1463 fputs("Identifier: <<<< ; >>>\n", stderr);
1464 fprintf(stderr, " enumeration=%p, function=%p, type=%p, type->child=%p, typedefnode=%p\n",
1465 enumeration, function, type, type ? type->child : NULL, typedefnode);
1466#endif /* DEBUG */
1467
1468 if (function)
1469 {
1470 if (!strcmp(tree->value.element.name, "class"))
1471 {
1472#ifdef DEBUG
1473 fputs(" ADDING FUNCTION TO CLASS\n", stderr);
1474#endif /* DEBUG */
1475 sort_node(tree, function);
1476 }
1477 else
1478 mxmlDelete(function);
1479
1480 function = NULL;
1481 variable = NULL;
1482 }
1483
1484 if (type)
1485 {
1486 /*
1487 * See if we have a typedef...
1488 */
1489
1490 if (type->child &&
1491 !strcmp(type->child->value.text.string, "typedef"))
1492 {
1493 /*
1494 * Yes, add it!
1495 */
1496
1497 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
1498
1499 for (node = type->child->next; node; node = node->next)
1500 if (!strcmp(node->value.text.string, "("))
1501 break;
1502
1503 if (node)
1504 {
1505 for (node = node->next; node; node = node->next)
1506 if (strcmp(node->value.text.string, "*"))
1507 break;
1508 }
1509
1510 if (!node)
1511 node = type->last_child;
1512
1513#ifdef DEBUG
1514 fprintf(stderr, " ADDING TYPEDEF FOR %p(%s)...\n",
1515 node, node->value.text.string);
1516#endif /* DEBUG */
1517
1518 mxmlElementSetAttr(typedefnode, "name",
1519 node->value.text.string);
1520 sort_node(tree, typedefnode);
1521
1522 if (type->child != node)
1523 mxmlDelete(type->child);
1524
1525 mxmlDelete(node);
1526
1527 if (type->child)
1528 type->child->value.text.whitespace = 0;
1529
1530 mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
1531 type);
1532 type = NULL;
1533 break;
1534 }
1535 else if (typedefnode && enumeration)
1536 {
1537 /*
1538 * Add enum typedef...
1539 */
1540
1541 node = type->child;
1542
1543#ifdef DEBUG
1544 fprintf(stderr, " ADDING TYPEDEF FOR %p(%s)...\n",
1545 node, node->value.text.string);
1546#endif /* DEBUG */
1547
1548 mxmlElementSetAttr(typedefnode, "name",
1549 node->value.text.string);
1550 sort_node(tree, typedefnode);
1551 mxmlDelete(type);
1552
1553 type = mxmlNewElement(typedefnode, "type");
1554 mxmlNewText(type, 0, "enum");
1555 mxmlNewText(type, 1,
1556 mxmlElementGetAttr(enumeration, "name"));
1557 enumeration = NULL;
1558 type = NULL;
1559 break;
1560 }
1561
1562 mxmlDelete(type);
1563 type = NULL;
1564 }
1565 break;
1566
1567 case ':' :
1568 if (type)
1569 {
1570#ifdef DEBUG
1571 fputs("Identifier: <<<< : >>>\n", stderr);
1572#endif /* DEBUG */
1573 mxmlNewText(type, 1, ":");
1574 }
1575 break;
1576
1577 case '*' :
1578 if (type)
1579 {
1580#ifdef DEBUG
1581 fputs("Identifier: <<<< * >>>\n", stderr);
1582#endif /* DEBUG */
1583 ch = type->last_child->value.text.string[0];
1584 mxmlNewText(type, isalnum(ch) || ch == '_', "*");
1585 }
1586 break;
1587
1588 case ',' :
1589 if (type && !enumeration)
1590 {
1591#ifdef DEBUG
1592 fputs("Identifier: <<<< , >>>\n", stderr);
1593#endif /* DEBUG */
1594 mxmlNewText(type, 0, ",");
1595 }
1596 break;
1597
1598 case '&' :
1599 if (type)
1600 {
1601#ifdef DEBUG
1602 fputs("Identifier: <<<< & >>>\n", stderr);
1603#endif /* DEBUG */
1604 mxmlNewText(type, 1, "&");
1605 }
1606 break;
1607
1608 case '+' :
1609 if (type)
1610 {
1611#ifdef DEBUG
1612 fputs("Identifier: <<<< + >>>\n", stderr);
1613#endif /* DEBUG */
1614 ch = type->last_child->value.text.string[0];
1615 mxmlNewText(type, isalnum(ch) || ch == '_', "+");
1616 }
1617 break;
1618
1619 case '-' :
1620 if (type)
1621 {
1622#ifdef DEBUG
1623 fputs("Identifier: <<<< - >>>\n", stderr);
1624#endif /* DEBUG */
1625 ch = type->last_child->value.text.string[0];
1626 mxmlNewText(type, isalnum(ch) || ch == '_', "-");
1627 }
1628 break;
1629
1630 case '=' :
1631 if (type)
1632 {
1633#ifdef DEBUG
1634 fputs("Identifier: <<<< = >>>\n", stderr);
1635#endif /* DEBUG */
1636 ch = type->last_child->value.text.string[0];
1637 mxmlNewText(type, isalnum(ch) || ch == '_', "=");
1638 }
1639 break;
1640
1641 default : /* Other */
1642 if (isalnum(ch) || ch == '_' || ch == '.' || ch == ':' || ch == '~')
1643 {
1644 state = STATE_IDENTIFIER;
1645 bufptr = buffer;
1646 *bufptr++ = ch;
1647 }
1648 break;
1649 }
1650 break;
1651
1652 case STATE_PREPROCESSOR : /* Preprocessor directive */
1653 if (ch == '\n')
1654 state = STATE_NONE;
1655 else if (ch == '\\')
1656 getc(fp);
1657 break;
1658
1659 case STATE_C_COMMENT : /* Inside a C comment */
1660 switch (ch)
1661 {
1662 case '\n' :
1663 while ((ch = getc(fp)) != EOF)
1664 if (ch == '*')
1665 {
1666 ch = getc(fp);
1667
1668 if (ch == '/')
1669 {
1670 *bufptr = '\0';
1671
1672 if (comment->child != comment->last_child)
1673 {
1674#ifdef DEBUG
1675 fprintf(stderr, " removing comment %p(%20.20s), last comment %p(%20.20s)...\n",
1676 comment->child,
1677 comment->child ? comment->child->value.text.string : "",
1678 comment->last_child,
1679 comment->last_child ? comment->last_child->value.text.string : "");
1680#endif /* DEBUG */
1681 mxmlDelete(comment->child);
1682#ifdef DEBUG
1683 fprintf(stderr, " new comment %p, last comment %p...\n",
1684 comment->child, comment->last_child);
1685#endif /* DEBUG */
1686 }
1687
1688#ifdef DEBUG
1689 fprintf(stderr,
1690 " processing comment, variable=%p, "
1691 "constant=%p, typedefnode=%p, tree=\"%s\"\n",
1692 variable, constant, typedefnode,
1693 tree->value.element.name);
1694#endif /* DEBUG */
1695
1696 if (variable)
1697 {
1698 if (strstr(buffer, "@private@"))
1699 {
1700 /*
1701 * Delete private variables...
1702 */
1703
1704 mxmlDelete(variable);
1705 }
1706 else
1707 {
1708 description = mxmlNewElement(variable, "description");
1709#ifdef DEBUG
1710 fprintf(stderr,
1711 " adding comment %p/%p to variable...\n",
1712 comment->last_child, comment->child);
1713#endif /* DEBUG */
1714 mxmlNewText(comment, 0, buffer);
1715 update_comment(variable,
1716 mxmlNewText(description, 0, buffer));
1717 }
1718
1719 variable = NULL;
1720 }
1721 else if (constant)
1722 {
1723 if (strstr(buffer, "@private@"))
1724 {
1725 /*
1726 * Delete private constants...
1727 */
1728
1729 mxmlDelete(constant);
1730 }
1731 else
1732 {
1733 description = mxmlNewElement(constant, "description");
1734#ifdef DEBUG
1735 fprintf(stderr,
1736 " adding comment %p/%p to constant...\n",
1737 comment->last_child, comment->child);
1738#endif /* DEBUG */
1739 mxmlNewText(comment, 0, buffer);
1740 update_comment(constant,
1741 mxmlNewText(description, 0, buffer));
1742 }
1743
1744 constant = NULL;
1745 }
1746 else if (typedefnode)
1747 {
1748 if (strstr(buffer, "@private@"))
1749 {
1750 /*
1751 * Delete private typedefs...
1752 */
1753
1754 mxmlDelete(typedefnode);
1755
1756 if (structclass)
1757 {
1758 mxmlDelete(structclass);
1759 structclass = NULL;
1760 }
1761
1762 if (enumeration)
1763 {
1764 mxmlDelete(enumeration);
1765 enumeration = NULL;
1766 }
1767 }
1768 else
1769 {
1770 description = mxmlNewElement(typedefnode, "description");
1771#ifdef DEBUG
1772 fprintf(stderr,
1773 " adding comment %p/%p to typedef %s...\n",
1774 comment->last_child, comment->child,
1775 mxmlElementGetAttr(typedefnode, "name"));
1776#endif /* DEBUG */
1777 mxmlNewText(comment, 0, buffer);
1778 update_comment(typedefnode,
1779 mxmlNewText(description, 0, buffer));
1780
1781 if (structclass)
1782 {
1783 description = mxmlNewElement(structclass, "description");
1784 update_comment(structclass,
1785 mxmlNewText(description, 0, buffer));
1786 }
1787 else if (enumeration)
1788 {
1789 description = mxmlNewElement(enumeration, "description");
1790 update_comment(enumeration,
1791 mxmlNewText(description, 0, buffer));
1792 }
1793 }
1794
1795 typedefnode = NULL;
1796 }
1797 else if (strcmp(tree->value.element.name, "mxmldoc") &&
1798 !mxmlFindElement(tree, tree, "description",
1799 NULL, NULL, MXML_DESCEND_FIRST))
1800 {
1801 description = mxmlNewElement(tree, "description");
1802#ifdef DEBUG
1803 fprintf(stderr, " adding comment %p/%p to parent...\n",
1804 comment->last_child, comment->child);
1805#endif /* DEBUG */
1806 mxmlNewText(comment, 0, buffer);
1807 update_comment(tree,
1808 mxmlNewText(description, 0, buffer));
1809 }
1810 else
1811 {
1812#ifdef DEBUG
1813 fprintf(stderr, " before adding comment, child=%p, last_child=%p\n",
1814 comment->child, comment->last_child);
1815#endif /* DEBUG */
1816 mxmlNewText(comment, 0, buffer);
1817#ifdef DEBUG
1818 fprintf(stderr, " after adding comment, child=%p, last_child=%p\n",
1819 comment->child, comment->last_child);
1820#endif /* DEBUG */
1821 }
1822#ifdef DEBUG
1823 fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
1824#endif /* DEBUG */
1825
1826 state = STATE_NONE;
1827 break;
1828 }
1829 else
1830 ungetc(ch, fp);
1831 }
1832 else if (ch == '\n' && bufptr > buffer &&
1833 bufptr < (buffer + sizeof(buffer) - 1))
1834 *bufptr++ = ch;
1835 else if (!isspace(ch))
1836 break;
1837
1838 if (ch != EOF)
1839 ungetc(ch, fp);
1840
1841 if (bufptr > buffer && bufptr < (buffer + sizeof(buffer) - 1))
1842 *bufptr++ = '\n';
1843 break;
1844
1845 case '/' :
1846 if (ch == '/' && bufptr > buffer && bufptr[-1] == '*')
1847 {
1848 while (bufptr > buffer &&
1849 (bufptr[-1] == '*' || isspace(bufptr[-1] & 255)))
1850 bufptr --;
1851 *bufptr = '\0';
1852
1853 if (comment->child != comment->last_child)
1854 {
1855#ifdef DEBUG
1856 fprintf(stderr, " removing comment %p(%20.20s), last comment %p(%20.20s)...\n",
1857 comment->child,
1858 comment->child ? comment->child->value.text.string : "",
1859 comment->last_child,
1860 comment->last_child ? comment->last_child->value.text.string : "");
1861#endif /* DEBUG */
1862 mxmlDelete(comment->child);
1863#ifdef DEBUG
1864 fprintf(stderr, " new comment %p, last comment %p...\n",
1865 comment->child, comment->last_child);
1866#endif /* DEBUG */
1867 }
1868
1869#ifdef DEBUG
1870 fprintf(stderr,
1871 " processing comment, variable=%p, "
1872 "constant=%p, typedefnode=%p, tree=\"%s\"\n",
1873 variable, constant, typedefnode,
1874 tree->value.element.name);
1875#endif /* DEBUG */
1876
1877 if (variable)
1878 {
1879 if (strstr(buffer, "@private@"))
1880 {
1881 /*
1882 * Delete private variables...
1883 */
1884
1885 mxmlDelete(variable);
1886 }
1887 else
1888 {
1889 description = mxmlNewElement(variable, "description");
1890#ifdef DEBUG
1891 fprintf(stderr, " adding comment %p/%p to variable...\n",
1892 comment->last_child, comment->child);
1893#endif /* DEBUG */
1894 mxmlNewText(comment, 0, buffer);
1895 update_comment(variable,
1896 mxmlNewText(description, 0, buffer));
1897 }
1898
1899 variable = NULL;
1900 }
1901 else if (constant)
1902 {
1903 if (strstr(buffer, "@private@"))
1904 {
1905 /*
1906 * Delete private constants...
1907 */
1908
1909 mxmlDelete(constant);
1910 }
1911 else
1912 {
1913 description = mxmlNewElement(constant, "description");
1914#ifdef DEBUG
1915 fprintf(stderr, " adding comment %p/%p to constant...\n",
1916 comment->last_child, comment->child);
1917#endif /* DEBUG */
1918 mxmlNewText(comment, 0, buffer);
1919 update_comment(constant,
1920 mxmlNewText(description, 0, buffer));
1921 }
1922
1923 constant = NULL;
1924 }
1925 else if (typedefnode)
1926 {
1927 if (strstr(buffer, "@private@"))
1928 {
1929 /*
1930 * Delete private typedefs...
1931 */
1932
1933 mxmlDelete(typedefnode);
1934
1935 if (structclass)
1936 {
1937 mxmlDelete(structclass);
1938 structclass = NULL;
1939 }
1940
1941 if (enumeration)
1942 {
1943 mxmlDelete(enumeration);
1944 enumeration = NULL;
1945 }
1946 }
1947 else
1948 {
1949 description = mxmlNewElement(typedefnode, "description");
1950#ifdef DEBUG
1951 fprintf(stderr,
1952 " adding comment %p/%p to typedef %s...\n",
1953 comment->last_child, comment->child,
1954 mxmlElementGetAttr(typedefnode, "name"));
1955#endif /* DEBUG */
1956 mxmlNewText(comment, 0, buffer);
1957 update_comment(typedefnode,
1958 mxmlNewText(description, 0, buffer));
1959
1960 if (structclass)
1961 {
1962 description = mxmlNewElement(structclass, "description");
1963 update_comment(structclass,
1964 mxmlNewText(description, 0, buffer));
1965 }
1966 else if (enumeration)
1967 {
1968 description = mxmlNewElement(enumeration, "description");
1969 update_comment(enumeration,
1970 mxmlNewText(description, 0, buffer));
1971 }
1972 }
1973
1974 typedefnode = NULL;
1975 }
1976 else if (strcmp(tree->value.element.name, "mxmldoc") &&
1977 !mxmlFindElement(tree, tree, "description",
1978 NULL, NULL, MXML_DESCEND_FIRST))
1979 {
1980 description = mxmlNewElement(tree, "description");
1981#ifdef DEBUG
1982 fprintf(stderr, " adding comment %p/%p to parent...\n",
1983 comment->last_child, comment->child);
1984#endif /* DEBUG */
1985 mxmlNewText(comment, 0, buffer);
1986 update_comment(tree,
1987 mxmlNewText(description, 0, buffer));
1988 }
1989 else
1990 mxmlNewText(comment, 0, buffer);
1991
1992#ifdef DEBUG
1993 fprintf(stderr, "C comment: <<<< %s >>>\n", buffer);
1994#endif /* DEBUG */
1995
1996 state = STATE_NONE;
1997 break;
1998 }
1999
2000 default :
2001 if (ch == ' ' && bufptr == buffer)
2002 break;
2003
2004 if (bufptr < (buffer + sizeof(buffer) - 1))
2005 *bufptr++ = ch;
2006 break;
2007 }
2008 break;
2009
2010 case STATE_CXX_COMMENT : /* Inside a C++ comment */
2011 if (ch == '\n')
2012 {
2013 state = STATE_NONE;
2014 *bufptr = '\0';
2015
2016 if (comment->child != comment->last_child)
2017 {
2018#ifdef DEBUG
2019 fprintf(stderr, " removing comment %p(%20.20s), last comment %p(%20.20s)...\n",
2020 comment->child,
2021 comment->child ? comment->child->value.text.string : "",
2022 comment->last_child,
2023 comment->last_child ? comment->last_child->value.text.string : "");
2024#endif /* DEBUG */
2025 mxmlDelete(comment->child);
2026#ifdef DEBUG
2027 fprintf(stderr, " new comment %p, last comment %p...\n",
2028 comment->child, comment->last_child);
2029#endif /* DEBUG */
2030 }
2031
2032 if (variable)
2033 {
2034 if (strstr(buffer, "@private@"))
2035 {
2036 /*
2037 * Delete private variables...
2038 */
2039
2040 mxmlDelete(variable);
2041 }
2042 else
2043 {
2044 description = mxmlNewElement(variable, "description");
2045#ifdef DEBUG
2046 fprintf(stderr, " adding comment %p/%p to variable...\n",
2047 comment->last_child, comment->child);
2048#endif /* DEBUG */
2049 mxmlNewText(comment, 0, buffer);
2050 update_comment(variable,
2051 mxmlNewText(description, 0, buffer));
2052 }
2053
2054 variable = NULL;
2055 }
2056 else if (constant)
2057 {
2058 if (strstr(buffer, "@private@"))
2059 {
2060 /*
2061 * Delete private constants...
2062 */
2063
2064 mxmlDelete(constant);
2065 }
2066 else
2067 {
2068 description = mxmlNewElement(constant, "description");
2069#ifdef DEBUG
2070 fprintf(stderr, " adding comment %p/%p to constant...\n",
2071 comment->last_child, comment->child);
2072#endif /* DEBUG */
2073 mxmlNewText(comment, 0, buffer);
2074 update_comment(constant,
2075 mxmlNewText(description, 0, buffer));
2076 }
2077
2078 constant = NULL;
2079 }
2080 else if (typedefnode)
2081 {
2082 if (strstr(buffer, "@private@"))
2083 {
2084 /*
2085 * Delete private typedefs...
2086 */
2087
2088 mxmlDelete(typedefnode);
2089 typedefnode = NULL;
2090
2091 if (structclass)
2092 {
2093 mxmlDelete(structclass);
2094 structclass = NULL;
2095 }
2096
2097 if (enumeration)
2098 {
2099 mxmlDelete(enumeration);
2100 enumeration = NULL;
2101 }
2102 }
2103 else
2104 {
2105 description = mxmlNewElement(typedefnode, "description");
2106#ifdef DEBUG
2107 fprintf(stderr, " adding comment %p/%p to typedef %s...\n",
2108 comment->last_child, comment->child,
2109 mxmlElementGetAttr(typedefnode, "name"));
2110#endif /* DEBUG */
2111 mxmlNewText(comment, 0, buffer);
2112 update_comment(typedefnode,
2113 mxmlNewText(description, 0, buffer));
2114
2115 if (structclass)
2116 {
2117 description = mxmlNewElement(structclass, "description");
2118 update_comment(structclass,
2119 mxmlNewText(description, 0, buffer));
2120 }
2121 else if (enumeration)
2122 {
2123 description = mxmlNewElement(enumeration, "description");
2124 update_comment(enumeration,
2125 mxmlNewText(description, 0, buffer));
2126 }
2127 }
2128 }
2129 else if (strcmp(tree->value.element.name, "mxmldoc") &&
2130 !mxmlFindElement(tree, tree, "description",
2131 NULL, NULL, MXML_DESCEND_FIRST))
2132 {
2133 description = mxmlNewElement(tree, "description");
2134#ifdef DEBUG
2135 fprintf(stderr, " adding comment %p/%p to parent...\n",
2136 comment->last_child, comment->child);
2137#endif /* DEBUG */
2138 mxmlNewText(comment, 0, buffer);
2139 update_comment(tree,
2140 mxmlNewText(description, 0, buffer));
2141 }
2142 else
2143 mxmlNewText(comment, 0, buffer);
2144
2145#ifdef DEBUG
2146 fprintf(stderr, "C++ comment: <<<< %s >>>\n", buffer);
2147#endif /* DEBUG */
2148 }
2149 else if (ch == ' ' && bufptr == buffer)
2150 break;
2151 else if (bufptr < (buffer + sizeof(buffer) - 1))
2152 *bufptr++ = ch;
2153 break;
2154
2155 case STATE_STRING : /* Inside a string constant */
2156 *bufptr++ = ch;
2157
2158 if (ch == '\\')
2159 *bufptr++ = getc(fp);
2160 else if (ch == '\"')
2161 {
2162 *bufptr = '\0';
2163
2164 if (type)
2165 mxmlNewText(type, type->child != NULL, buffer);
2166
2167 state = STATE_NONE;
2168 }
2169 break;
2170
2171 case STATE_CHARACTER : /* Inside a character constant */
2172 *bufptr++ = ch;
2173
2174 if (ch == '\\')
2175 *bufptr++ = getc(fp);
2176 else if (ch == '\'')
2177 {
2178 *bufptr = '\0';
2179
2180 if (type)
2181 mxmlNewText(type, type->child != NULL, buffer);
2182
2183 state = STATE_NONE;
2184 }
2185 break;
2186
2187 case STATE_IDENTIFIER : /* Inside a keyword or identifier */
2188 if (isalnum(ch) || ch == '_' || ch == '[' || ch == ']' ||
2189 (ch == ',' && (parens > 1 || (type && !enumeration && !function))) ||
2190 ch == ':' || ch == '.' || ch == '~')
2191 {
2192 if (bufptr < (buffer + sizeof(buffer) - 1))
2193 *bufptr++ = ch;
2194 }
2195 else
2196 {
2197 ungetc(ch, fp);
2198 *bufptr = '\0';
2199 state = STATE_NONE;
2200
2201#ifdef DEBUG
2202 fprintf(stderr, " braces=%d, type=%p, type->child=%p, buffer=\"%s\"\n",
2203 braces, type, type ? type->child : NULL, buffer);
2204#endif /* DEBUG */
2205
2206 if (!braces)
2207 {
2208 if (!type || !type->child)
2209 {
2210 if (!strcmp(tree->value.element.name, "class"))
2211 {
2212 if (!strcmp(buffer, "public") ||
2213 !strcmp(buffer, "public:"))
2214 {
2215 scope = "public";
2216#ifdef DEBUG
2217 fputs(" scope = public\n", stderr);
2218#endif /* DEBUG */
2219 break;
2220 }
2221 else if (!strcmp(buffer, "private") ||
2222 !strcmp(buffer, "private:"))
2223 {
2224 scope = "private";
2225#ifdef DEBUG
2226 fputs(" scope = private\n", stderr);
2227#endif /* DEBUG */
2228 break;
2229 }
2230 else if (!strcmp(buffer, "protected") ||
2231 !strcmp(buffer, "protected:"))
2232 {
2233 scope = "protected";
2234#ifdef DEBUG
2235 fputs(" scope = protected\n", stderr);
2236#endif /* DEBUG */
2237 break;
2238 }
2239 }
2240 }
2241
2242 if (!type)
2243 type = mxmlNewElement(MXML_NO_PARENT, "type");
2244
2245#ifdef DEBUG
2246 fprintf(stderr, " function=%p (%s), type->child=%p, ch='%c', parens=%d\n",
2247 function,
2248 function ? mxmlElementGetAttr(function, "name") : "null",
2249 type->child, ch, parens);
2250#endif /* DEBUG */
2251
2252 if (!function && ch == '(')
2253 {
2254 if (type->child &&
2255 !strcmp(type->child->value.text.string, "extern"))
2256 {
2257 /*
2258 * Remove external declarations...
2259 */
2260
2261 mxmlDelete(type);
2262 type = NULL;
2263 break;
2264 }
2265
2266 if (type->child &&
2267 !strcmp(type->child->value.text.string, "static") &&
2268 !strcmp(tree->value.element.name, "mxmldoc"))
2269 {
2270 /*
2271 * Remove static functions...
2272 */
2273
2274 mxmlDelete(type);
2275 type = NULL;
2276 break;
2277 }
2278
2279 function = mxmlNewElement(MXML_NO_PARENT, "function");
2280 if ((bufptr = strchr(buffer, ':')) != NULL && bufptr[1] == ':')
2281 {
2282 *bufptr = '\0';
2283 bufptr += 2;
2284
2285 if ((fstructclass =
2286 mxmlFindElement(tree, tree, "class", "name", buffer,
2287 MXML_DESCEND_FIRST)) == NULL)
2288 fstructclass =
2289 mxmlFindElement(tree, tree, "struct", "name", buffer,
2290 MXML_DESCEND_FIRST);
2291 }
2292 else
2293 bufptr = buffer;
2294
2295 mxmlElementSetAttr(function, "name", bufptr);
2296
2297 if (scope)
2298 mxmlElementSetAttr(function, "scope", scope);
2299
2300#ifdef DEBUG
2301 fprintf(stderr, "function: %s\n", buffer);
2302 fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
2303 fprintf(stderr, " comment = %p\n", comment);
2304 fprintf(stderr, " child = (%p) %s\n",
2305 comment->child,
2306 comment->child ?
2307 comment->child->value.text.string : "(null)");
2308 fprintf(stderr, " last_child = (%p) %s\n",
2309 comment->last_child,
2310 comment->last_child ?
2311 comment->last_child->value.text.string : "(null)");
2312#endif /* DEBUG */
2313
2314 if (type->last_child &&
2315 strcmp(type->last_child->value.text.string, "void"))
2316 {
2317 returnvalue = mxmlNewElement(function, "returnvalue");
2318
2319 mxmlAdd(returnvalue, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
2320
2321 description = mxmlNewElement(returnvalue, "description");
2322#ifdef DEBUG
2323 fprintf(stderr, " adding comment %p/%p to returnvalue...\n",
2324 comment->last_child, comment->child);
2325#endif /* DEBUG */
2326 update_comment(returnvalue, comment->last_child);
2327 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
2328 comment->last_child);
2329 }
2330 else
2331 mxmlDelete(type);
2332
2333 description = mxmlNewElement(function, "description");
2334#ifdef DEBUG
2335 fprintf(stderr, " adding comment %p/%p to function...\n",
2336 comment->last_child, comment->child);
2337#endif /* DEBUG */
2338 update_comment(function, comment->last_child);
2339 mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT,
2340 comment->last_child);
2341
2342 type = NULL;
2343 }
2344 else if (function && ((ch == ')' && parens == 1) || ch == ','))
2345 {
2346 /*
2347 * Argument definition...
2348 */
2349
2350 if (strcmp(buffer, "void"))
2351 {
2352 mxmlNewText(type, type->child != NULL &&
2353 type->last_child->value.text.string[0] != '(' &&
2354 type->last_child->value.text.string[0] != '*',
2355 buffer);
2356
2357#ifdef DEBUG
2358 fprintf(stderr, "Argument: <<<< %s >>>\n", buffer);
2359#endif /* DEBUG */
2360
2361 variable = add_variable(function, "argument", type);
2362 }
2363 else
2364 mxmlDelete(type);
2365
2366 type = NULL;
2367 }
2368 else if (type->child && !function && (ch == ';' || ch == ','))
2369 {
2370#ifdef DEBUG
2371 fprintf(stderr, " got semicolon, typedefnode=%p, structclass=%p\n",
2372 typedefnode, structclass);
2373#endif /* DEBUG */
2374
2375 if (typedefnode || structclass)
2376 {
2377#ifdef DEBUG
2378 fprintf(stderr, "Typedef/struct/class: <<<< %s >>>>\n", buffer);
2379#endif /* DEBUG */
2380
2381 if (typedefnode)
2382 {
2383 mxmlElementSetAttr(typedefnode, "name", buffer);
2384
2385 sort_node(tree, typedefnode);
2386 }
2387
2388 if (structclass && !mxmlElementGetAttr(structclass, "name"))
2389 {
2390#ifdef DEBUG
2391 fprintf(stderr, "setting struct/class name to %s!\n",
2392 type->last_child->value.text.string);
2393#endif /* DEBUG */
2394 mxmlElementSetAttr(structclass, "name", buffer);
2395
2396 sort_node(tree, structclass);
2397 structclass = NULL;
2398 }
2399
2400 if (typedefnode)
2401 mxmlAdd(typedefnode, MXML_ADD_BEFORE, MXML_ADD_TO_PARENT,
2402 type);
2403 else
2404 mxmlDelete(type);
2405
2406 type = NULL;
2407 typedefnode = NULL;
2408 }
2409 else if (type->child &&
2410 !strcmp(type->child->value.text.string, "typedef"))
2411 {
2412 /*
2413 * Simple typedef...
2414 */
2415
2416#ifdef DEBUG
2417 fprintf(stderr, "Typedef: <<<< %s >>>\n", buffer);
2418#endif /* DEBUG */
2419
2420 typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
2421 mxmlElementSetAttr(typedefnode, "name", buffer);
2422 mxmlDelete(type->child);
2423
2424 sort_node(tree, typedefnode);
2425
2426 if (type->child)
2427 type->child->value.text.whitespace = 0;
2428
2429 mxmlAdd(typedefnode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, type);
2430 type = NULL;
2431 }
2432 else if (!parens)
2433 {
2434 /*
2435 * Variable definition...
2436 */
2437
2438 if (type->child &&
2439 !strcmp(type->child->value.text.string, "static") &&
2440 !strcmp(tree->value.element.name, "mxmldoc"))
2441 {
2442 /*
2443 * Remove static functions...
2444 */
2445
2446 mxmlDelete(type);
2447 type = NULL;
2448 break;
2449 }
2450
2451 mxmlNewText(type, type->child != NULL &&
2452 type->last_child->value.text.string[0] != '(' &&
2453 type->last_child->value.text.string[0] != '*',
2454 buffer);
2455
2456#ifdef DEBUG
2457 fprintf(stderr, "Variable: <<<< %s >>>>\n", buffer);
2458 fprintf(stderr, " scope = %s\n", scope ? scope : "(null)");
2459#endif /* DEBUG */
2460
2461 variable = add_variable(MXML_NO_PARENT, "variable", type);
2462 type = NULL;
2463
2464 sort_node(tree, variable);
2465
2466 if (scope)
2467 mxmlElementSetAttr(variable, "scope", scope);
2468 }
2469 }
2470 else
2471 {
2472#ifdef DEBUG
2473 fprintf(stderr, "Identifier: <<<< %s >>>>\n", buffer);
2474#endif /* DEBUG */
2475
2476 mxmlNewText(type, type->child != NULL &&
2477 type->last_child->value.text.string[0] != '(' &&
2478 type->last_child->value.text.string[0] != '*',
2479 buffer);
2480 }
2481 }
2482 else if (enumeration && !isdigit(buffer[0] & 255))
2483 {
2484#ifdef DEBUG
2485 fprintf(stderr, "Constant: <<<< %s >>>\n", buffer);
2486#endif /* DEBUG */
2487
2488 constant = mxmlNewElement(MXML_NO_PARENT, "constant");
2489 mxmlElementSetAttr(constant, "name", buffer);
2490 sort_node(enumeration, constant);
2491 }
2492 else if (type)
2493 {
2494 mxmlDelete(type);
2495 type = NULL;
2496 }
2497 }
2498 break;
2499 }
2500
2501#if DEBUG > 1
2502 if (state != oldstate)
2503 {
2504 fprintf(stderr, " changed states from %s to %s on receipt of character '%c'...\n",
2505 states[oldstate], states[state], oldch);
2506 fprintf(stderr, " variable = %p\n", variable);
2507 if (type)
2508 {
2509 fputs(" type =", stderr);
2510 for (temp = type->child; temp; temp = temp->next)
2511 fprintf(stderr, " \"%s\"", temp->value.text.string);
2512 fputs("\n", stderr);
2513 }
2514 }
2515#endif /* DEBUG > 1 */
2516 }
2517
2518 mxmlDelete(comment);
2519
2520 /*
2521 * All done, return with no errors...
2522 */
2523
2524 return (0);
2525}
2526
2527
2528/*
2529 * 'sort_node()' - Insert a node sorted into a tree.
2530 */
2531
2532static void
2533sort_node(mxml_node_t *tree, /* I - Tree to sort into */
2534 mxml_node_t *node) /* I - Node to add */
2535{
2536 mxml_node_t *temp; /* Current node */
2537 const char *tempname, /* Name of current node */
2538 *nodename, /* Name of node */
2539 *scope; /* Scope */
2540
2541
2542#if DEBUG > 1
2543 fprintf(stderr, " sort_node(tree=%p, node=%p)\n", tree, node);
2544#endif /* DEBUG > 1 */
2545
2546 /*
2547 * Range check input...
2548 */
2549
2550 if (!tree || !node || node->parent == tree)
2551 return;
2552
2553 /*
2554 * Get the node name...
2555 */
2556
2557 if ((nodename = mxmlElementGetAttr(node, "name")) == NULL)
2558 return;
2559
2560 if (nodename[0] == '_')
2561 return; /* Hide private names */
2562
2563#if DEBUG > 1
2564 fprintf(stderr, " nodename=%p (\"%s\")\n", nodename, nodename);
2565#endif /* DEBUG > 1 */
2566
2567 /*
2568 * Delete any existing definition at this level, if one exists...
2569 */
2570
2571 if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
2572 "name", nodename, MXML_DESCEND_FIRST)) != NULL)
2573 {
2574 /*
2575 * Copy the scope if needed...
2576 */
2577
2578 if ((scope = mxmlElementGetAttr(temp, "scope")) != NULL &&
2579 mxmlElementGetAttr(node, "scope") == NULL)
2580 {
2581#ifdef DEBUG
2582 fprintf(stderr, " copying scope %s for %s\n", scope, nodename);
2583#endif /* DEBUG */
2584
2585 mxmlElementSetAttr(node, "scope", scope);
2586 }
2587
2588 mxmlDelete(temp);
2589 }
2590
2591 /*
2592 * Add the node into the tree at the proper place...
2593 */
2594
2595 for (temp = tree->child; temp; temp = temp->next)
2596 {
2597#if DEBUG > 1
2598 fprintf(stderr, " temp=%p\n", temp);
2599#endif /* DEBUG > 1 */
2600
2601 if ((tempname = mxmlElementGetAttr(temp, "name")) == NULL)
2602 continue;
2603
2604#if DEBUG > 1
2605 fprintf(stderr, " tempname=%p (\"%s\")\n", tempname, tempname);
2606#endif /* DEBUG > 1 */
2607
2608 if (strcmp(nodename, tempname) < 0)
2609 break;
2610 }
2611
2612 if (temp)
2613 mxmlAdd(tree, MXML_ADD_BEFORE, temp, node);
2614 else
2615 mxmlAdd(tree, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
2616}
2617
2618
2619/*
2620 * 'update_comment()' - Update a comment node.
2621 */
2622
2623static void
2624update_comment(mxml_node_t *parent, /* I - Parent node */
2625 mxml_node_t *comment) /* I - Comment node */
2626{
2627 char *ptr; /* Pointer into comment */
2628
2629
2630#ifdef DEBUG
2631 fprintf(stderr, "update_comment(parent=%p, comment=%p)\n",
2632 parent, comment);
2633#endif /* DEBUG */
2634
2635 /*
2636 * Range check the input...
2637 */
2638
2639 if (!parent || !comment)
2640 return;
2641
2642 /*
2643 * Convert "\/" to "/"...
2644 */
2645
2646 for (ptr = strstr(comment->value.text.string, "\\/");
2647 ptr;
2648 ptr = strstr(ptr, "\\/"))
2649 safe_strcpy(ptr, ptr + 1);
2650
2651 /*
2652 * Update the comment...
2653 */
2654
2655 ptr = comment->value.text.string;
2656
2657 if (*ptr == '\'')
2658 {
2659 /*
2660 * Convert "'name()' - description" to "description".
2661 */
2662
2663 for (ptr ++; *ptr && *ptr != '\''; ptr ++);
2664
2665 if (*ptr == '\'')
2666 {
2667 ptr ++;
2668 while (isspace(*ptr & 255))
2669 ptr ++;
2670
2671 if (*ptr == '-')
2672 ptr ++;
2673
2674 while (isspace(*ptr & 255))
2675 ptr ++;
2676
2677 safe_strcpy(comment->value.text.string, ptr);
2678 }
2679 }
2680 else if (!strncmp(ptr, "I ", 2) || !strncmp(ptr, "O ", 2) ||
2681 !strncmp(ptr, "IO ", 3))
2682 {
2683 /*
2684 * 'Convert "I - description", "IO - description", or "O - description"
2685 * to description + direction attribute.
2686 */
2687
2688 ptr = strchr(ptr, ' ');
2689 *ptr++ = '\0';
2690
2691 if (!strcmp(parent->value.element.name, "argument"))
2692 mxmlElementSetAttr(parent, "direction", comment->value.text.string);
2693
2694 while (isspace(*ptr & 255))
2695 ptr ++;
2696
2697 if (*ptr == '-')
2698 ptr ++;
2699
2700 while (isspace(*ptr & 255))
2701 ptr ++;
2702
2703 safe_strcpy(comment->value.text.string, ptr);
2704 }
2705
2706 /*
2707 * Eliminate leading and trailing *'s...
2708 */
2709
2710 for (ptr = comment->value.text.string; *ptr == '*'; ptr ++);
2711 for (; isspace(*ptr & 255); ptr ++);
2712 if (ptr > comment->value.text.string)
2713 safe_strcpy(comment->value.text.string, ptr);
2714
2715 for (ptr = comment->value.text.string + strlen(comment->value.text.string) - 1;
2716 ptr > comment->value.text.string && *ptr == '*';
2717 ptr --)
2718 *ptr = '\0';
2719 for (; ptr > comment->value.text.string && isspace(*ptr & 255); ptr --)
2720 *ptr = '\0';
2721
2722#ifdef DEBUG
2723 fprintf(stderr, " updated comment = %s\n", comment->value.text.string);
2724#endif /* DEBUG */
2725}
2726
2727
2728/*
2729 * 'usage()' - Show program usage...
2730 */
2731
2732static void
2733usage(const char *option) /* I - Unknown option */
2734{
2735 if (option)
2736 printf("mxmldoc: Bad option \"%s\"!\n\n", option);
2737
2738 puts("Usage: mxmldoc [options] [filename.xml] [source files] >filename.html");
2739 puts("Options:");
2740 puts(" --css filename.css Set CSS stylesheet file");
2741 puts(" --docset bundleid.docset Generate documentation set");
2742 puts(" --docversion version Set documentation version");
2743 puts(" --feedname name Set documentation set feed name");
2744 puts(" --feedurl url Set documentation set feed URL");
2745 puts(" --footer footerfile Set footer file");
2746 puts(" --framed basename Generate framed HTML to basename*.html");
2747 puts(" --header headerfile Set header file");
2748 puts(" --intro introfile Set introduction file");
2749 puts(" --man name Generate man page");
2750 puts(" --no-output Do no generate documentation file");
2751 puts(" --section section Set section name");
2752 puts(" --title title Set documentation title");
2753 puts(" --tokens path Generate Xcode docset Tokens.xml file");
2754 puts(" --version Show mxmldoc/Mini-XML version");
2755
2756 exit(1);
2757}
2758
2759
2760/*
2761 * 'write_description()' - Write the description text.
2762 */
2763
2764static void
2765write_description(
2766 FILE *out, /* I - Output file */
2767 mxml_node_t *description, /* I - Description node */
2768 const char *element, /* I - HTML element, if any */
2769 int summary) /* I - Show summary */
2770{
2771 char text[10240], /* Text for description */
2772 *start, /* Start of code/link */
2773 *ptr; /* Pointer into text */
2774 int col; /* Current column */
2775
2776
2777 if (!description)
2778 return;
2779
2780 get_text(description, text, sizeof(text));
2781
2782 ptr = strstr(text, "\n\n");
2783
2784 if (summary)
2785 {
2786 if (ptr)
2787 *ptr = '\0';
2788
2789 ptr = text;
2790 }
2791 else if (!ptr || !ptr[2])
2792 return;
2793 else
2794 ptr += 2;
2795
2796 if (element && *element)
2797 fprintf(out, "<%s class=\"%s\">", element,
2798 summary ? "description" : "discussion");
2799 else if (!summary)
2800 fputs(".PP\n", out);
2801
2802 for (col = 0; *ptr; ptr ++)
2803 {
2804 if (*ptr == '@' &&
2805 (!strncmp(ptr + 1, "deprecated@", 11) ||
2806 !strncmp(ptr + 1, "since ", 6)))
2807 {
2808 ptr ++;
2809 while (*ptr && *ptr != '@')
2810 ptr ++;
2811
2812 if (!*ptr)
2813 return;
2814 }
2815 else if (!strncmp(ptr, "@code ", 6))
2816 {
2817 for (ptr += 6; isspace(*ptr & 255); ptr ++);
2818
2819 for (start = ptr, ptr ++; *ptr && *ptr != '@'; ptr ++);
2820
2821 if (*ptr)
2822 *ptr = '\0';
2823 else
2824 ptr --;
2825
2826 if (element && *element)
2827 fprintf(out, "<code>%s</code>", start);
2828 else if (element)
2829 fputs(start, out);
2830 else
2831 fprintf(out, "\\fB%s\\fR", start);
2832 }
2833 else if (!strncmp(ptr, "@link ", 6))
2834 {
2835 for (ptr += 6; isspace(*ptr & 255); ptr ++);
2836
2837 for (start = ptr, ptr ++; *ptr && *ptr != '@'; ptr ++);
2838
2839 if (*ptr)
2840 *ptr = '\0';
2841 else
2842 ptr --;
2843
2844 if (element && *element)
2845 fprintf(out, "<a href=\"#%s\"><code>%s</code></a>", start, start);
2846 else if (element)
2847 fputs(start, out);
2848 else
2849 fprintf(out, "\\fI%s\\fR", start);
2850 }
2851 else if (element)
2852 {
2853 if (*ptr == '&')
2854 fputs("&amp;", out);
2855 else if (*ptr == '<')
2856 fputs("&lt;", out);
2857 else if (*ptr == '>')
2858 fputs("&gt;", out);
2859 else if (*ptr == '\"')
2860 fputs("&quot;", out);
2861 else if (*ptr & 128)
2862 {
2863 /*
2864 * Convert UTF-8 to Unicode constant...
2865 */
2866
2867 int ch; /* Unicode character */
2868
2869
2870 ch = *ptr & 255;
2871
2872 if ((ch & 0xe0) == 0xc0)
2873 {
2874 ch = ((ch & 0x1f) << 6) | (ptr[1] & 0x3f);
2875 ptr ++;
2876 }
2877 else if ((ch & 0xf0) == 0xe0)
2878 {
2879 ch = ((((ch * 0x0f) << 6) | (ptr[1] & 0x3f)) << 6) | (ptr[2] & 0x3f);
2880 ptr += 2;
2881 }
2882
2883 if (ch == 0xa0)
2884 {
2885 /*
2886 * Handle non-breaking space as-is...
2887 */
2888
2889 fputs("&nbsp;", out);
2890 }
2891 else
2892 fprintf(out, "&#x%x;", ch);
2893 }
2894 else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@')
2895 {
2896 fputs("<br>\n<br>\n", out);
2897 ptr ++;
2898 }
2899 else
2900 putc(*ptr, out);
2901 }
2902 else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@')
2903 {
2904 fputs("\n.PP\n", out);
2905 ptr ++;
2906 }
2907 else
2908 {
2909 if (*ptr == '\\' || (*ptr == '.' && col == 0))
2910 putc('\\', out);
2911
2912 putc(*ptr, out);
2913
2914 if (*ptr == '\n')
2915 col = 0;
2916 else
2917 col ++;
2918 }
2919 }
2920
2921 if (element && *element)
2922 fprintf(out, "</%s>\n", element);
2923 else if (!element)
2924 putc('\n', out);
2925}
2926
2927
2928/*
2929 * 'write_element()' - Write an element's text nodes.
2930 */
2931
2932static void
2933write_element(FILE *out, /* I - Output file */
2934 mxml_node_t *doc, /* I - Document tree */
2935 mxml_node_t *element, /* I - Element to write */
2936 int mode) /* I - Output mode */
2937{
2938 mxml_node_t *node; /* Current node */
2939
2940
2941 if (!element)
2942 return;
2943
2944 for (node = element->child;
2945 node;
2946 node = mxmlWalkNext(node, element, MXML_NO_DESCEND))
2947 if (node->type == MXML_TEXT)
2948 {
2949 if (node->value.text.whitespace)
2950 putc(' ', out);
2951
2952 if (mode == OUTPUT_HTML &&
2953 (mxmlFindElement(doc, doc, "class", "name", node->value.text.string,
2954 MXML_DESCEND) ||
2955 mxmlFindElement(doc, doc, "enumeration", "name",
2956 node->value.text.string, MXML_DESCEND) ||
2957 mxmlFindElement(doc, doc, "struct", "name", node->value.text.string,
2958 MXML_DESCEND) ||
2959 mxmlFindElement(doc, doc, "typedef", "name", node->value.text.string,
2960 MXML_DESCEND) ||
2961 mxmlFindElement(doc, doc, "union", "name", node->value.text.string,
2962 MXML_DESCEND)))
2963 {
2964 fputs("<a href=\"#", out);
2965 write_string(out, node->value.text.string, mode);
2966 fputs("\">", out);
2967 write_string(out, node->value.text.string, mode);
2968 fputs("</a>", out);
2969 }
2970 else
2971 write_string(out, node->value.text.string, mode);
2972 }
2973
2974 if (!strcmp(element->value.element.name, "type") &&
2975 element->last_child->value.text.string[0] != '*')
2976 putc(' ', out);
2977}
2978
2979
2980/*
2981 * 'write_file()' - Copy a file to the output.
2982 */
2983
2984static void
2985write_file(FILE *out, /* I - Output file */
2986 const char *file) /* I - File to copy */
2987{
2988 FILE *fp; /* Copy file */
2989 char line[8192]; /* Line from file */
2990
2991
2992 if ((fp = fopen(file, "r")) == NULL)
2993 {
2994 fprintf(stderr, "mxmldoc: Unable to open \"%s\": %s\n", file,
2995 strerror(errno));
2996 return;
2997 }
2998
2999 while (fgets(line, sizeof(line), fp))
3000 fputs(line, out);
3001
3002 fclose(fp);
3003}
3004
3005
3006/*
3007 * 'write_function()' - Write documentation for a function.
3008 */
3009
3010static void
3011write_function(FILE *out, /* I - Output file */
3012 mxml_node_t *doc, /* I - Document */
3013 mxml_node_t *function, /* I - Function */
3014 int level) /* I - Base heading level */
3015{
3016 mxml_node_t *arg, /* Current argument */
3017 *adesc, /* Description of argument */
3018 *description, /* Description of function */
3019 *type, /* Type for argument */
3020 *node; /* Node in description */
3021 const char *name, /* Name of function/type */
3022 *defval; /* Default value */
3023 char prefix; /* Prefix character */
3024 char *sep; /* Newline separator */
3025
3026
3027 name = mxmlElementGetAttr(function, "name");
3028 description = mxmlFindElement(function, function, "description", NULL,
3029 NULL, MXML_DESCEND_FIRST);
3030
3031 fprintf(out, "<h%d class=\"%s\">%s<a name=\"%s\">%s</a></h%d>\n",
3032 level, level == 3 ? "function" : "method",
3033 get_comment_info(description), name, name, level);
3034
3035 if (description)
3036 write_description(out, description, "p", 1);
3037
3038 fputs("<p class=\"code\">\n", out);
3039
3040 arg = mxmlFindElement(function, function, "returnvalue", NULL,
3041 NULL, MXML_DESCEND_FIRST);
3042
3043 if (arg)
3044 write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
3045 NULL, MXML_DESCEND_FIRST),
3046 OUTPUT_HTML);
3047 else
3048 fputs("void ", out);
3049
3050 fprintf(out, "%s ", name);
3051 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
3052 MXML_DESCEND_FIRST), prefix = '(';
3053 arg;
3054 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
3055 MXML_NO_DESCEND), prefix = ',')
3056 {
3057 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
3058 MXML_DESCEND_FIRST);
3059
3060 fprintf(out, "%c<br>\n&nbsp;&nbsp;&nbsp;&nbsp;", prefix);
3061 if (type->child)
3062 write_element(out, doc, type, OUTPUT_HTML);
3063
3064 fputs(mxmlElementGetAttr(arg, "name"), out);
3065 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
3066 fprintf(out, " %s", defval);
3067 }
3068
3069 if (prefix == '(')
3070 fputs("(void);</p>\n", out);
3071 else
3072 {
3073 fprintf(out,
3074 "<br>\n);</p>\n"
3075 "<h%d class=\"parameters\">Parameters</h%d>\n"
3076 "<dl>\n", level + 1, level + 1);
3077
3078 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
3079 MXML_DESCEND_FIRST);
3080 arg;
3081 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
3082 MXML_NO_DESCEND))
3083 {
3084 fprintf(out, "<dt>%s</dt>\n", mxmlElementGetAttr(arg, "name"));
3085
3086 adesc = mxmlFindElement(arg, arg, "description", NULL, NULL,
3087 MXML_DESCEND_FIRST);
3088
3089 write_description(out, adesc, "dd", 1);
3090 write_description(out, adesc, "dd", 0);
3091 }
3092
3093 fputs("</dl>\n", out);
3094 }
3095
3096 arg = mxmlFindElement(function, function, "returnvalue", NULL,
3097 NULL, MXML_DESCEND_FIRST);
3098
3099 if (arg)
3100 {
3101 fprintf(out, "<h%d class=\"returnvalue\">Return Value</h%d>\n", level + 1,
3102 level + 1);
3103
3104 adesc = mxmlFindElement(arg, arg, "description", NULL, NULL,
3105 MXML_DESCEND_FIRST);
3106
3107 write_description(out, adesc, "p", 1);
3108 write_description(out, adesc, "p", 0);
3109 }
3110
3111 if (description)
3112 {
3113 for (node = description->child; node; node = node->next)
3114 if (node->value.text.string &&
3115 (sep = strstr(node->value.text.string, "\n\n")) != NULL)
3116 {
3117 sep += 2;
3118 if (*sep && strncmp(sep, "@since ", 7) &&
3119 strncmp(sep, "@deprecated@", 12))
3120 break;
3121 }
3122
3123 if (node)
3124 {
3125 fprintf(out, "<h%d class=\"discussion\">Discussion</h%d>\n", level + 1,
3126 level + 1);
3127 write_description(out, description, "p", 0);
3128 }
3129 }
3130}
3131
3132
3133/*
3134 * 'write_html()' - Write HTML documentation.
3135 */
3136
3137static void
3138write_html(const char *section, /* I - Section */
3139 const char *title, /* I - Title */
3140 const char *footerfile, /* I - Footer file */
3141 const char *headerfile, /* I - Header file */
3142 const char *introfile, /* I - Intro file */
3143 const char *cssfile, /* I - Stylesheet file */
3144 const char *framefile, /* I - Framed HTML basename */
3145 const char *docset, /* I - Documentation set directory */
3146 const char *docversion, /* I - Documentation set version */
3147 const char *feedname, /* I - Feed name for doc set */
3148 const char *feedurl, /* I - Feed URL for doc set */
3149 mxml_node_t *doc) /* I - XML documentation */
3150{
3151 FILE *out; /* Output file */
3152 mxml_node_t *function, /* Current function */
3153 *scut, /* Struct/class/union/typedef */
3154 *arg, /* Current argument */
3155 *description, /* Description of function/var */
3156 *type; /* Type for argument */
3157 const char *name, /* Name of function/type */
3158 *defval, /* Default value */
3159 *basename; /* Base filename for framed output */
3160 char filename[1024]; /* Current output filename */
3161
3162
3163 if (framefile)
3164 {
3165 /*
3166 * Get the basename of the frame file...
3167 */
3168
3169 if ((basename = strrchr(framefile, '/')) != NULL)
3170 basename ++;
3171 else
3172 basename = framefile;
3173
3174 if (strstr(basename, ".html"))
3175 fputs("mxmldoc: Frame base name should not contain .html extension!\n",
3176 stderr);
3177
3178 /*
3179 * Create the container HTML file for the frames...
3180 */
3181
3182 snprintf(filename, sizeof(filename), "%s.html", framefile);
3183
3184 if ((out = fopen(filename, "w")) == NULL)
3185 {
3186 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3187 strerror(errno));
3188 return;
3189 }
3190
3191 fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" "
3192 "\"http://www.w3.org/TR/html4/frameset.dtd\">\n"
3193 "<html>\n"
3194 "<head>\n"
3195 "\t<title>", out);
3196 write_string(out, title, OUTPUT_HTML);
3197 fputs("</title>\n", out);
3198
3199 if (section)
3200 fprintf(out, "\t<meta name=\"keywords\" content=\"%s\">\n", section);
3201
3202 fputs("\t<meta http-equiv=\"Content-Type\" "
3203 "content=\"text/html;charset=utf-8\">\n"
3204 "\t<meta name=\"creator\" content=\"" MXML_VERSION "\">\n"
3205 "</head>\n", out);
3206
3207 fputs("<frameset cols=\"250,*\">\n", out);
3208 fprintf(out, "<frame src=\"%s-toc.html\">\n", basename);
3209 fprintf(out, "<frame name=\"body\" src=\"%s-body.html\">\n", basename);
3210 fputs("</frameset>\n"
3211 "<noframes>\n"
3212 "<h1>", out);
3213 write_string(out, title, OUTPUT_HTML);
3214 fprintf(out,
3215 "</h1>\n"
3216 "<ul>\n"
3217 "\t<li><a href=\"%s-toc.html\">Table of Contents</a></li>\n"
3218 "\t<li><a href=\"%s-body.html\">Body</a></li>\n"
3219 "</ul>\n", basename, basename);
3220 fputs("</noframes>\n"
3221 "</html>\n", out);
3222 fclose(out);
3223
3224 /*
3225 * Write the table-of-contents file...
3226 */
3227
3228 snprintf(filename, sizeof(filename), "%s-toc.html", framefile);
3229
3230 if ((out = fopen(filename, "w")) == NULL)
3231 {
3232 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3233 strerror(errno));
3234 return;
3235 }
3236
3237 write_html_head(out, section, title, cssfile);
3238
3239 snprintf(filename, sizeof(filename), "%s-body.html", basename);
3240
3241 fputs("<div class=\"contents\">\n", out);
3242 fprintf(out, "<h1 class=\"title\"><a href=\"%s\" target=\"body\">",
3243 filename);
3244 write_string(out, title, OUTPUT_HTML);
3245 fputs("</a></h1>\n", out);
3246
3247 write_toc(out, doc, introfile, filename, 0);
3248
3249 fputs("</div>\n"
3250 "</body>\n"
3251 "</html>\n", out);
3252 fclose(out);
3253
3254 /*
3255 * Finally, open the body file...
3256 */
3257
3258 snprintf(filename, sizeof(filename), "%s-body.html", framefile);
3259
3260 if ((out = fopen(filename, "w")) == NULL)
3261 {
3262 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3263 strerror(errno));
3264 return;
3265 }
3266 }
3267 else if (docset)
3268 {
3269 /*
3270 * Create an Xcode documentation set - start by removing any existing
3271 * output directory...
3272 */
3273
3274#ifdef __APPLE__
3275 const char *id; /* Identifier */
3276
3277
3278 if (!access(docset, 0) && !remove_directory(docset))
3279 return;
3280
3281 /*
3282 * Then make the Apple standard bundle directory structure...
3283 */
3284
3285 if (mkdir(docset, 0755))
3286 {
3287 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", docset,
3288 strerror(errno));
3289 return;
3290 }
3291
3292 snprintf(filename, sizeof(filename), "%s/Contents", docset);
3293 if (mkdir(filename, 0755))
3294 {
3295 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3296 strerror(errno));
3297 return;
3298 }
3299
3300 snprintf(filename, sizeof(filename), "%s/Contents/Resources", docset);
3301 if (mkdir(filename, 0755))
3302 {
3303 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3304 strerror(errno));
3305 return;
3306 }
3307
3308 snprintf(filename, sizeof(filename), "%s/Contents/Resources/Documentation",
3309 docset);
3310 if (mkdir(filename, 0755))
3311 {
3312 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3313 strerror(errno));
3314 return;
3315 }
3316
3317 /*
3318 * The Info.plist file, which describes the documentation set...
3319 */
3320
3321 if ((id = strrchr(docset, '/')) != NULL)
3322 id ++;
3323 else
3324 id = docset;
3325
3326 snprintf(filename, sizeof(filename), "%s/Contents/Info.plist", docset);
3327 if ((out = fopen(filename, "w")) == NULL)
3328 {
3329 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3330 strerror(errno));
3331 return;
3332 }
3333
3334 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
3335 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
3336 "<plist version=\"1.0\">\n"
3337 "<dict>\n"
3338 "\t<key>CFBundleIdentifier</key>\n"
3339 "\t<string>", out);
3340 write_string(out, id, OUTPUT_HTML);
3341 fputs("</string>\n"
3342 "\t<key>CFBundleName</key>\n"
3343 "\t<string>", out);
3344 write_string(out, title, OUTPUT_HTML);
3345 fputs("</string>\n"
3346 "\t<key>CFBundleVersion</key>\n"
3347 "\t<string>", out);
3348 write_string(out, docversion ? docversion : "0.0", OUTPUT_HTML);
3349 fputs("</string>\n"
3350 "\t<key>CFBundleShortVersionString</key>\n"
3351 "\t<string>", out);
3352 write_string(out, docversion ? docversion : "0.0", OUTPUT_HTML);
3353 fputs("</string>\n", out);
3354
3355 if (feedname)
3356 {
3357 fputs("\t<key>DocSetFeedName</key>\n"
3358 "\t<string>", out);
3359 write_string(out, feedname ? feedname : title, OUTPUT_HTML);
3360 fputs("</string>\n", out);
3361 }
3362
3363 if (feedurl)
3364 {
3365 fputs("\t<key>DocSetFeedURL</key>\n"
3366 "\t<string>", out);
3367 write_string(out, feedurl, OUTPUT_HTML);
3368 fputs("</string>\n", out);
3369 }
3370
3371 fputs("</dict>\n"
3372 "</plist>\n", out);
3373
3374 fclose(out);
3375
3376 /*
3377 * Next the Nodes.xml file...
3378 */
3379
3380 snprintf(filename, sizeof(filename), "%s/Contents/Resources/Nodes.xml",
3381 docset);
3382 if ((out = fopen(filename, "w")) == NULL)
3383 {
3384 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3385 strerror(errno));
3386 return;
3387 }
3388
3389 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
3390 "<DocSetNodes version=\"1.0\">\n"
3391 "<TOC>\n"
3392 "<Node id=\"0\">\n"
3393 "<Name>", out);
3394 write_string(out, title, OUTPUT_HTML);
3395 fputs("</Name>\n"
3396 "<Path>Documentation/index.html</Path>\n"
3397 "<Subnodes>\n", out);
3398
3399 write_toc(out, doc, introfile, NULL, 1);
3400
3401 fputs("</Subnodes>\n"
3402 "</Node>\n"
3403 "</TOC>\n"
3404 "</DocSetNodes>\n", out);
3405
3406 fclose(out);
3407
3408 /*
3409 * Then the Tokens.xml file...
3410 */
3411
3412 snprintf(filename, sizeof(filename), "%s/Contents/Resources/Tokens.xml",
3413 docset);
3414 if ((out = fopen(filename, "w")) == NULL)
3415 {
3416 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3417 strerror(errno));
3418 return;
3419 }
3420
3421 fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
3422 "<Tokens version=\"1.0\">\n", out);
3423
3424 write_tokens(out, doc, "index.html");
3425
3426 fputs("</Tokens>\n", out);
3427
3428 fclose(out);
3429
3430 /*
3431 * Finally the HTML file...
3432 */
3433
3434 snprintf(filename, sizeof(filename),
3435 "%s/Contents/Resources/Documentation/index.html",
3436 docset);
3437 if ((out = fopen(filename, "w")) == NULL)
3438 {
3439 fprintf(stderr, "mxmldoc: Unable to create \"%s\": %s\n", filename,
3440 strerror(errno));
3441 return;
3442 }
3443
3444#else
3445 fputs("mxmldoc: Xcode documentation sets can only be created on "
3446 "Mac OS X.\n", stderr);
3447 return;
3448#endif /* __APPLE__ */
3449 }
3450 else
3451 out = stdout;
3452
3453 /*
3454 * Standard header...
3455 */
3456
3457 write_html_head(out, section, title, cssfile);
3458
3459 fputs("<div class='body'>\n", out);
3460
3461 /*
3462 * Header...
3463 */
3464
3465 if (headerfile)
3466 {
3467 /*
3468 * Use custom header...
3469 */
3470
3471 write_file(out, headerfile);
3472 }
3473 else
3474 {
3475 /*
3476 * Use standard header...
3477 */
3478
3479 fputs("<h1 class=\"title\">", out);
3480 write_string(out, title, OUTPUT_HTML);
3481 fputs("</h1>\n", out);
3482 }
3483
3484 /*
3485 * Table of contents...
3486 */
3487
3488 if (!framefile)
3489 write_toc(out, doc, introfile, NULL, 0);
3490
3491 /*
3492 * Intro...
3493 */
3494
3495 if (introfile)
3496 write_file(out, introfile);
3497
3498 /*
3499 * List of classes...
3500 */
3501
3502 if ((scut = find_public(doc, doc, "class")) != NULL)
3503 {
3504 fputs("<h2 class=\"title\"><a name=\"CLASSES\">Classes</a></h2>\n", out);
3505
3506 while (scut)
3507 {
3508 write_scu(out, doc, scut);
3509
3510 scut = find_public(scut, doc, "class");
3511 }
3512 }
3513
3514 /*
3515 * List of functions...
3516 */
3517
3518 if ((function = find_public(doc, doc, "function")) != NULL)
3519 {
3520 fputs("<h2 class=\"title\"><a name=\"FUNCTIONS\">Functions</a></h2>\n", out);
3521
3522 while (function)
3523 {
3524 write_function(out, doc, function, 3);
3525
3526 function = find_public(function, doc, "function");
3527 }
3528 }
3529
3530 /*
3531 * List of types...
3532 */
3533
3534 if ((scut = find_public(doc, doc, "typedef")) != NULL)
3535 {
3536 fputs("<h2 class=\"title\"><a name=\"TYPES\">Data Types</a></h2>\n", out);
3537
3538 while (scut)
3539 {
3540 name = mxmlElementGetAttr(scut, "name");
3541 description = mxmlFindElement(scut, scut, "description", NULL,
3542 NULL, MXML_DESCEND_FIRST);
3543 fprintf(out, "<h3 class=\"typedef\">%s<a name=\"%s\">%s</a></h3>\n",
3544 get_comment_info(description), name, name);
3545
3546 if (description)
3547 write_description(out, description, "p", 1);
3548
3549 fputs("<p class=\"code\">\n"
3550 "typedef ", out);
3551
3552 type = mxmlFindElement(scut, scut, "type", NULL, NULL,
3553 MXML_DESCEND_FIRST);
3554
3555 for (type = type->child; type; type = type->next)
3556 if (!strcmp(type->value.text.string, "("))
3557 break;
3558 else
3559 {
3560 if (type->value.text.whitespace)
3561 putc(' ', out);
3562
3563 if (mxmlFindElement(doc, doc, "class", "name",
3564 type->value.text.string, MXML_DESCEND) ||
3565 mxmlFindElement(doc, doc, "enumeration", "name",
3566 type->value.text.string, MXML_DESCEND) ||
3567 mxmlFindElement(doc, doc, "struct", "name",
3568 type->value.text.string, MXML_DESCEND) ||
3569 mxmlFindElement(doc, doc, "typedef", "name",
3570 type->value.text.string, MXML_DESCEND) ||
3571 mxmlFindElement(doc, doc, "union", "name",
3572 type->value.text.string, MXML_DESCEND))
3573 {
3574 fputs("<a href=\"#", out);
3575 write_string(out, type->value.text.string, OUTPUT_HTML);
3576 fputs("\">", out);
3577 write_string(out, type->value.text.string, OUTPUT_HTML);
3578 fputs("</a>", out);
3579 }
3580 else
3581 write_string(out, type->value.text.string, OUTPUT_HTML);
3582 }
3583
3584 if (type)
3585 {
3586 /*
3587 * Output function type...
3588 */
3589
3590 if (type->prev && type->prev->value.text.string[0] != '*')
3591 putc(' ', out);
3592
3593 fprintf(out, "(*%s", name);
3594
3595 for (type = type->next->next; type; type = type->next)
3596 {
3597 if (type->value.text.whitespace)
3598 putc(' ', out);
3599
3600 if (mxmlFindElement(doc, doc, "class", "name",
3601 type->value.text.string, MXML_DESCEND) ||
3602 mxmlFindElement(doc, doc, "enumeration", "name",
3603 type->value.text.string, MXML_DESCEND) ||
3604 mxmlFindElement(doc, doc, "struct", "name",
3605 type->value.text.string, MXML_DESCEND) ||
3606 mxmlFindElement(doc, doc, "typedef", "name",
3607 type->value.text.string, MXML_DESCEND) ||
3608 mxmlFindElement(doc, doc, "union", "name",
3609 type->value.text.string, MXML_DESCEND))
3610 {
3611 fputs("<a href=\"#", out);
3612 write_string(out, type->value.text.string, OUTPUT_HTML);
3613 fputs("\">", out);
3614 write_string(out, type->value.text.string, OUTPUT_HTML);
3615 fputs("</a>", out);
3616 }
3617 else
3618 write_string(out, type->value.text.string, OUTPUT_HTML);
3619 }
3620
3621 fputs(";\n", out);
3622 }
3623 else
3624 {
3625 type = mxmlFindElement(scut, scut, "type", NULL, NULL,
3626 MXML_DESCEND_FIRST);
3627 if (type->last_child->value.text.string[0] != '*')
3628 putc(' ', out);
3629
3630 fprintf(out, "%s;\n", name);
3631 }
3632
3633 fputs("</p>\n", out);
3634
3635 scut = find_public(scut, doc, "typedef");
3636 }
3637 }
3638
3639 /*
3640 * List of structures...
3641 */
3642
3643 if ((scut = find_public(doc, doc, "struct")) != NULL)
3644 {
3645 fputs("<h2 class=\"title\"><a name=\"STRUCTURES\">Structures</a></h2>\n",
3646 out);
3647
3648 while (scut)
3649 {
3650 write_scu(out, doc, scut);
3651
3652 scut = find_public(scut, doc, "struct");
3653 }
3654 }
3655
3656 /*
3657 * List of unions...
3658 */
3659
3660 if ((scut = find_public(doc, doc, "union")) != NULL)
3661 {
3662 fputs("<h2 class=\"title\"><a name=\"UNIONS\">Unions</a></h2>\n", out);
3663
3664 while (scut)
3665 {
3666 write_scu(out, doc, scut);
3667
3668 scut = find_public(scut, doc, "union");
3669 }
3670 }
3671
3672 /*
3673 * Variables...
3674 */
3675
3676 if ((arg = find_public(doc, doc, "variable")) != NULL)
3677 {
3678 fputs("<h2 class=\"title\"><a name=\"VARIABLES\">Variables</a></h2>\n",
3679 out);
3680
3681 while (arg)
3682 {
3683 name = mxmlElementGetAttr(arg, "name");
3684 description = mxmlFindElement(arg, arg, "description", NULL,
3685 NULL, MXML_DESCEND_FIRST);
3686 fprintf(out, "<h3 class=\"variable\">%s<a name=\"%s\">%s</a></h3>\n",
3687 get_comment_info(description), name, name);
3688
3689 if (description)
3690 write_description(out, description, "p", 1);
3691
3692 fputs("<p class=\"code\">", out);
3693
3694 write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
3695 NULL, MXML_DESCEND_FIRST),
3696 OUTPUT_HTML);
3697 fputs(mxmlElementGetAttr(arg, "name"), out);
3698 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
3699 fprintf(out, " %s", defval);
3700 fputs(";</p>\n", out);
3701
3702 arg = find_public(arg, doc, "variable");
3703 }
3704 }
3705
3706 /*
3707 * List of enumerations...
3708 */
3709
3710 if ((scut = find_public(doc, doc, "enumeration")) != NULL)
3711 {
3712 fputs("<h2 class=\"title\"><a name=\"ENUMERATIONS\">Constants</a></h2>\n",
3713 out);
3714
3715 while (scut)
3716 {
3717 name = mxmlElementGetAttr(scut, "name");
3718 description = mxmlFindElement(scut, scut, "description", NULL,
3719 NULL, MXML_DESCEND_FIRST);
3720 fprintf(out, "<h3 class=\"enumeration\">%s<a name=\"%s\">%s</a></h3>\n",
3721 get_comment_info(description), name, name);
3722
3723 if (description)
3724 write_description(out, description, "p", 1);
3725
3726 fputs("<h4 class=\"constants\">Constants</h4>\n"
3727 "<dl>\n", out);
3728
3729 for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
3730 MXML_DESCEND_FIRST);
3731 arg;
3732 arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
3733 MXML_NO_DESCEND))
3734 {
3735 description = mxmlFindElement(arg, arg, "description", NULL,
3736 NULL, MXML_DESCEND_FIRST);
3737 fprintf(out, "<dt>%s %s</dt>\n",
3738 mxmlElementGetAttr(arg, "name"), get_comment_info(description));
3739
3740 write_description(out, description, "dd", 1);
3741 write_description(out, description, "dd", 0);
3742 }
3743
3744 fputs("</dl>\n", out);
3745
3746 scut = find_public(scut, doc, "enumeration");
3747 }
3748 }
3749
3750 /*
3751 * Footer...
3752 */
3753
3754 if (footerfile)
3755 {
3756 /*
3757 * Use custom footer...
3758 */
3759
3760 write_file(out, footerfile);
3761 }
3762
3763 fputs("</div>\n"
3764 "</body>\n"
3765 "</html>\n", out);
3766
3767 /*
3768 * Close output file as needed...
3769 */
3770
3771 if (out != stdout)
3772 fclose(out);
3773
3774#ifdef __APPLE__
3775 /*
3776 * When generating document sets, run the docsetutil program to index it...
3777 */
3778
3779 if (docset)
3780 {
3781 const char *args[4]; /* Argument array */
3782 pid_t pid; /* Process ID */
3783 int status; /* Exit status */
3784
3785
3786 args[0] = "/Developer/usr/bin/docsetutil";
3787 args[1] = "index";
3788 args[2] = docset;
3789 args[3] = NULL;
3790
3791 if (posix_spawn(&pid, args[0], NULL, NULL, (char **)args, environ))
3792 {
3793 fprintf(stderr, "mxmldoc: Unable to index documentation set \"%s\": %s\n",
3794 docset, strerror(errno));
3795 }
3796 else
3797 {
3798 while (wait(&status) != pid);
3799
3800 if (status)
3801 {
3802 if (WIFEXITED(status))
3803 fprintf(stderr, "mxmldoc: docsetutil exited with status %d\n",
3804 WEXITSTATUS(status));
3805 else
3806 fprintf(stderr, "mxmldoc: docsetutil crashed with signal %d\n",
3807 WTERMSIG(status));
3808 }
3809 else
3810 {
3811 /*
3812 * Remove unneeded temporary XML files...
3813 */
3814
3815 snprintf(filename, sizeof(filename), "%s/Contents/Resources/Nodes.xml",
3816 docset);
3817 unlink(filename);
3818
3819 snprintf(filename, sizeof(filename), "%s/Contents/Resources/Tokens.xml",
3820 docset);
3821 unlink(filename);
3822 }
3823 }
3824 }
3825#endif /* __APPLE__ */
3826}
3827
3828
3829/*
3830 * 'write_html_head()' - Write the standard HTML header.
3831 */
3832
3833static void
3834write_html_head(FILE *out, /* I - Output file */
3835 const char *section, /* I - Section */
3836 const char *title, /* I - Title */
3837 const char *cssfile) /* I - Stylesheet */
3838{
3839 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
3840 "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
3841 "<html>\n", out);
3842
3843 if (section)
3844 fprintf(out, "<!-- SECTION: %s -->\n", section);
3845
3846 fputs("<head>\n"
3847 "\t<title>", out);
3848 write_string(out, title, OUTPUT_HTML);
3849 fputs("\t</title>\n", out);
3850
3851 if (section)
3852 fprintf(out, "\t<meta name=\"keywords\" content=\"%s\">\n", section);
3853
3854 fputs("\t<meta http-equiv=\"Content-Type\" "
3855 "content=\"text/html;charset=utf-8\">\n"
3856 "\t<meta name=\"creator\" content=\"" MXML_VERSION "\">\n"
3857 "<style type=\"text/css\"><!--\n", out);
3858
3859 if (cssfile)
3860 {
3861 /*
3862 * Use custom stylesheet file...
3863 */
3864
3865 write_file(out, cssfile);
3866 }
3867 else
3868 {
3869 /*
3870 * Use standard stylesheet...
3871 */
3872
3873 fputs("body, p, h1, h2, h3, h4 {\n"
3874 " font-family: \"lucida grande\", geneva, helvetica, arial, "
3875 "sans-serif;\n"
3876 "}\n"
3877 "div.body h1 {\n"
3878 " font-size: 250%;\n"
3879 " font-weight: bold;\n"
3880 " margin: 0;\n"
3881 "}\n"
3882 "div.body h2 {\n"
3883 " font-size: 250%;\n"
3884 " margin-top: 1.5em;\n"
3885 "}\n"
3886 "div.body h3 {\n"
3887 " font-size: 150%;\n"
3888 " margin-bottom: 0.5em;\n"
3889 " margin-top: 1.5em;\n"
3890 "}\n"
3891 "div.body h4 {\n"
3892 " font-size: 110%;\n"
3893 " margin-bottom: 0.5em;\n"
3894 " margin-top: 1.5em;\n"
3895 "}\n"
3896 "div.body h5 {\n"
3897 " font-size: 100%;\n"
3898 " margin-bottom: 0.5em;\n"
3899 " margin-top: 1.5em;\n"
3900 "}\n"
3901 "div.contents {\n"
3902 " background: #e8e8e8;\n"
3903 " border: solid thin black;\n"
3904 " padding: 10px;\n"
3905 "}\n"
3906 "div.contents h1 {\n"
3907 " font-size: 110%;\n"
3908 "}\n"
3909 "div.contents h2 {\n"
3910 " font-size: 100%;\n"
3911 "}\n"
3912 "div.contents ul.contents {\n"
3913 " font-size: 80%;\n"
3914 "}\n"
3915 ".class {\n"
3916 " border-bottom: solid 2px gray;\n"
3917 "}\n"
3918 ".constants {\n"
3919 "}\n"
3920 ".description {\n"
3921 " margin-top: 0.5em;\n"
3922 "}\n"
3923 ".discussion {\n"
3924 "}\n"
3925 ".enumeration {\n"
3926 " border-bottom: solid 2px gray;\n"
3927 "}\n"
3928 ".function {\n"
3929 " border-bottom: solid 2px gray;\n"
3930 " margin-bottom: 0;\n"
3931 "}\n"
3932 ".members {\n"
3933 "}\n"
3934 ".method {\n"
3935 "}\n"
3936 ".parameters {\n"
3937 "}\n"
3938 ".returnvalue {\n"
3939 "}\n"
3940 ".struct {\n"
3941 " border-bottom: solid 2px gray;\n"
3942 "}\n"
3943 ".typedef {\n"
3944 " border-bottom: solid 2px gray;\n"
3945 "}\n"
3946 ".union {\n"
3947 " border-bottom: solid 2px gray;\n"
3948 "}\n"
3949 ".variable {\n"
3950 "}\n"
3951 "code, p.code, pre, ul.code li {\n"
3952 " font-family: monaco, courier, monospace;\n"
3953 " font-size: 90%;\n"
3954 "}\n"
3955 "a:link, a:visited {\n"
3956 " text-decoration: none;\n"
3957 "}\n"
3958 "span.info {\n"
3959 " background: black;\n"
3960 " border: solid thin black;\n"
3961 " color: white;\n"
3962 " font-size: 80%;\n"
3963 " font-style: italic;\n"
3964 " font-weight: bold;\n"
3965 " white-space: nowrap;\n"
3966 "}\n"
3967 "h3 span.info, h4 span.info {\n"
3968 " float: right;\n"
3969 " font-size: 100%;\n"
3970 "}\n"
3971 "ul.code, ul.contents, ul.subcontents {\n"
3972 " list-style-type: none;\n"
3973 " margin: 0;\n"
3974 " padding-left: 0;\n"
3975 "}\n"
3976 "ul.code li {\n"
3977 " margin: 0;\n"
3978 "}\n"
3979 "ul.contents > li {\n"
3980 " margin-top: 1em;\n"
3981 "}\n"
3982 "ul.contents li ul.code, ul.contents li ul.subcontents {\n"
3983 " padding-left: 2em;\n"
3984 "}\n"
3985 "div.body dl {\n"
3986 " margin-top: 0;\n"
3987 "}\n"
3988 "div.body dt {\n"
3989 " font-style: italic;\n"
3990 " margin-top: 0;\n"
3991 "}\n"
3992 "div.body dd {\n"
3993 " margin-bottom: 0.5em;\n"
3994 "}\n"
3995 "h1.title {\n"
3996 "}\n"
3997 "h2.title {\n"
3998 " border-bottom: solid 2px black;\n"
3999 "}\n"
4000 "h3.title {\n"
4001 " border-bottom: solid 2px black;\n"
4002 "}\n", out);
4003 }
4004
4005 fputs("--></style>\n"
4006 "</head>\n"
4007 "<body>\n", out);
4008}
4009
4010
4011/*
4012 * 'write_man()' - Write manpage documentation.
4013 */
4014
4015static void
4016write_man(const char *man_name, /* I - Name of manpage */
4017 const char *section, /* I - Section */
4018 const char *title, /* I - Title */
4019 const char *footerfile, /* I - Footer file */
4020 const char *headerfile, /* I - Header file */
4021 const char *introfile, /* I - Intro file */
4022 mxml_node_t *doc) /* I - XML documentation */
4023{
4024 int i; /* Looping var */
4025 mxml_node_t *function, /* Current function */
4026 *scut, /* Struct/class/union/typedef */
4027 *arg, /* Current argument */
4028 *description, /* Description of function/var */
4029 *type; /* Type for argument */
4030 const char *name, /* Name of function/type */
4031 *cname, /* Class name */
4032 *defval, /* Default value */
4033 *parent; /* Parent class */
4034 int inscope; /* Variable/method scope */
4035 char prefix; /* Prefix character */
4036 time_t curtime; /* Current time */
4037 struct tm *curdate; /* Current date */
4038 char buffer[1024]; /* String buffer */
4039 static const char * const scopes[] = /* Scope strings */
4040 {
4041 "private",
4042 "protected",
4043 "public"
4044 };
4045
4046
4047 /*
4048 * Standard man page...
4049 */
4050
4051 curtime = time(NULL);
4052 curdate = localtime(&curtime);
4053 strftime(buffer, sizeof(buffer), "%x", curdate);
4054
4055 printf(".TH %s %s \"%s\" \"%s\" \"%s\"\n", man_name, section ? section : "3",
4056 title ? title : "", buffer, title ? title : "");
4057
4058 /*
4059 * Header...
4060 */
4061
4062 if (headerfile)
4063 {
4064 /*
4065 * Use custom header...
4066 */
4067
4068 write_file(stdout, headerfile);
4069 }
4070 else
4071 {
4072 /*
4073 * Use standard header...
4074 */
4075
4076 puts(".SH NAME");
4077 printf("%s \\- %s\n", man_name, title ? title : man_name);
4078 }
4079
4080 /*
4081 * Intro...
4082 */
4083
4084 if (introfile)
4085 write_file(stdout, introfile);
4086
4087 /*
4088 * List of classes...
4089 */
4090
4091 if (find_public(doc, doc, "class"))
4092 {
4093 puts(".SH CLASSES");
4094
4095 for (scut = find_public(doc, doc, "class");
4096 scut;
4097 scut = find_public(scut, doc, "class"))
4098 {
4099 cname = mxmlElementGetAttr(scut, "name");
4100 description = mxmlFindElement(scut, scut, "description", NULL,
4101 NULL, MXML_DESCEND_FIRST);
4102 printf(".SS %s\n", cname);
4103
4104 write_description(stdout, description, NULL, 1);
4105
4106 printf(".PP\n"
4107 ".nf\n"
4108 "class %s", cname);
4109 if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
4110 printf(" %s", parent);
4111 puts("\n{");
4112
4113 for (i = 0; i < 3; i ++)
4114 {
4115 inscope = 0;
4116
4117 for (arg = mxmlFindElement(scut, scut, "variable", "scope", scopes[i],
4118 MXML_DESCEND_FIRST);
4119 arg;
4120 arg = mxmlFindElement(arg, scut, "variable", "scope", scopes[i],
4121 MXML_NO_DESCEND))
4122 {
4123 if (!inscope)
4124 {
4125 inscope = 1;
4126 printf(" %s:\n", scopes[i]);
4127 }
4128
4129 printf(" ");
4130 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4131 NULL, MXML_DESCEND_FIRST),
4132 OUTPUT_MAN);
4133 printf("%s;\n", mxmlElementGetAttr(arg, "name"));
4134 }
4135
4136 for (function = mxmlFindElement(scut, scut, "function", "scope",
4137 scopes[i], MXML_DESCEND_FIRST);
4138 function;
4139 function = mxmlFindElement(function, scut, "function", "scope",
4140 scopes[i], MXML_NO_DESCEND))
4141 {
4142 if (!inscope)
4143 {
4144 inscope = 1;
4145 printf(" %s:\n", scopes[i]);
4146 }
4147
4148 name = mxmlElementGetAttr(function, "name");
4149
4150 printf(" ");
4151
4152 arg = mxmlFindElement(function, function, "returnvalue", NULL,
4153 NULL, MXML_DESCEND_FIRST);
4154
4155 if (arg)
4156 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4157 NULL, MXML_DESCEND_FIRST),
4158 OUTPUT_MAN);
4159 else if (strcmp(cname, name) && strcmp(cname, name + 1))
4160 fputs("void ", stdout);
4161
4162 printf("%s", name);
4163
4164 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
4165 MXML_DESCEND_FIRST), prefix = '(';
4166 arg;
4167 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
4168 MXML_NO_DESCEND), prefix = ',')
4169 {
4170 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
4171 MXML_DESCEND_FIRST);
4172
4173 putchar(prefix);
4174 if (prefix == ',')
4175 putchar(' ');
4176
4177 if (type->child)
4178 write_element(stdout, doc, type, OUTPUT_MAN);
4179 fputs(mxmlElementGetAttr(arg, "name"), stdout);
4180 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
4181 printf(" %s", defval);
4182 }
4183
4184 if (prefix == '(')
4185 puts("(void);");
4186 else
4187 puts(");");
4188 }
4189 }
4190
4191 puts("};\n"
4192 ".fi");
4193
4194 write_description(stdout, description, NULL, 0);
4195 }
4196 }
4197
4198 /*
4199 * List of enumerations...
4200 */
4201
4202 if (find_public(doc, doc, "enumeration"))
4203 {
4204 puts(".SH ENUMERATIONS");
4205
4206 for (scut = find_public(doc, doc, "enumeration");
4207 scut;
4208 scut = find_public(scut, doc, "enumeration"))
4209 {
4210 name = mxmlElementGetAttr(scut, "name");
4211 description = mxmlFindElement(scut, scut, "description", NULL,
4212 NULL, MXML_DESCEND_FIRST);
4213 printf(".SS %s\n", name);
4214
4215 write_description(stdout, description, NULL, 1);
4216 write_description(stdout, description, NULL, 0);
4217
4218 for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
4219 MXML_DESCEND_FIRST);
4220 arg;
4221 arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
4222 MXML_NO_DESCEND))
4223 {
4224 description = mxmlFindElement(arg, arg, "description", NULL,
4225 NULL, MXML_DESCEND_FIRST);
4226 printf(".TP 5\n%s\n.br\n", mxmlElementGetAttr(arg, "name"));
4227 write_description(stdout, description, NULL, 1);
4228 }
4229 }
4230 }
4231
4232 /*
4233 * List of functions...
4234 */
4235
4236 if (find_public(doc, doc, "function"))
4237 {
4238 puts(".SH FUNCTIONS");
4239
4240 for (function = find_public(doc, doc, "function");
4241 function;
4242 function = find_public(function, doc, "function"))
4243 {
4244 name = mxmlElementGetAttr(function, "name");
4245 description = mxmlFindElement(function, function, "description", NULL,
4246 NULL, MXML_DESCEND_FIRST);
4247 printf(".SS %s\n", name);
4248
4249 write_description(stdout, description, NULL, 1);
4250
4251 puts(".PP\n"
4252 ".nf");
4253
4254 arg = mxmlFindElement(function, function, "returnvalue", NULL,
4255 NULL, MXML_DESCEND_FIRST);
4256
4257 if (arg)
4258 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4259 NULL, MXML_DESCEND_FIRST),
4260 OUTPUT_MAN);
4261 else
4262 fputs("void", stdout);
4263
4264 printf(" %s ", name);
4265 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
4266 MXML_DESCEND_FIRST), prefix = '(';
4267 arg;
4268 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
4269 MXML_NO_DESCEND), prefix = ',')
4270 {
4271 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
4272 MXML_DESCEND_FIRST);
4273
4274 printf("%c\n ", prefix);
4275 if (type->child)
4276 write_element(stdout, doc, type, OUTPUT_MAN);
4277 fputs(mxmlElementGetAttr(arg, "name"), stdout);
4278 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
4279 printf(" %s", defval);
4280 }
4281
4282 if (prefix == '(')
4283 puts("(void);");
4284 else
4285 puts("\n);");
4286
4287 puts(".fi");
4288
4289 write_description(stdout, description, NULL, 0);
4290 }
4291 }
4292
4293 /*
4294 * List of structures...
4295 */
4296
4297 if (find_public(doc, doc, "struct"))
4298 {
4299 puts(".SH STRUCTURES");
4300
4301 for (scut = find_public(doc, doc, "struct");
4302 scut;
4303 scut = find_public(scut, doc, "struct"))
4304 {
4305 cname = mxmlElementGetAttr(scut, "name");
4306 description = mxmlFindElement(scut, scut, "description", NULL,
4307 NULL, MXML_DESCEND_FIRST);
4308 printf(".SS %s\n", cname);
4309
4310 write_description(stdout, description, NULL, 1);
4311
4312 printf(".PP\n"
4313 ".nf\n"
4314 "struct %s\n{\n", cname);
4315 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
4316 MXML_DESCEND_FIRST);
4317 arg;
4318 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
4319 MXML_NO_DESCEND))
4320 {
4321 printf(" ");
4322 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4323 NULL, MXML_DESCEND_FIRST),
4324 OUTPUT_MAN);
4325 printf("%s;\n", mxmlElementGetAttr(arg, "name"));
4326 }
4327
4328 for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
4329 MXML_DESCEND_FIRST);
4330 function;
4331 function = mxmlFindElement(function, scut, "function", NULL, NULL,
4332 MXML_NO_DESCEND))
4333 {
4334 name = mxmlElementGetAttr(function, "name");
4335
4336 printf(" ");
4337
4338 arg = mxmlFindElement(function, function, "returnvalue", NULL,
4339 NULL, MXML_DESCEND_FIRST);
4340
4341 if (arg)
4342 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4343 NULL, MXML_DESCEND_FIRST),
4344 OUTPUT_MAN);
4345 else if (strcmp(cname, name) && strcmp(cname, name + 1))
4346 fputs("void ", stdout);
4347
4348 fputs(name, stdout);
4349
4350 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
4351 MXML_DESCEND_FIRST), prefix = '(';
4352 arg;
4353 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
4354 MXML_NO_DESCEND), prefix = ',')
4355 {
4356 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
4357 MXML_DESCEND_FIRST);
4358
4359 putchar(prefix);
4360 if (prefix == ',')
4361 putchar(' ');
4362
4363 if (type->child)
4364 write_element(stdout, doc, type, OUTPUT_MAN);
4365 fputs(mxmlElementGetAttr(arg, "name"), stdout);
4366 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
4367 printf(" %s", defval);
4368 }
4369
4370 if (prefix == '(')
4371 puts("(void);");
4372 else
4373 puts(");");
4374 }
4375
4376 puts("};\n"
4377 ".fi");
4378
4379 write_description(stdout, description, NULL, 0);
4380 }
4381 }
4382
4383 /*
4384 * List of types...
4385 */
4386
4387 if (find_public(doc, doc, "typedef"))
4388 {
4389 puts(".SH TYPES");
4390
4391 for (scut = find_public(doc, doc, "typedef");
4392 scut;
4393 scut = find_public(scut, doc, "typedef"))
4394 {
4395 name = mxmlElementGetAttr(scut, "name");
4396 description = mxmlFindElement(scut, scut, "description", NULL,
4397 NULL, MXML_DESCEND_FIRST);
4398 printf(".SS %s\n", name);
4399
4400 write_description(stdout, description, NULL, 1);
4401
4402 fputs(".PP\n"
4403 ".nf\n"
4404 "typedef ", stdout);
4405
4406 type = mxmlFindElement(scut, scut, "type", NULL, NULL,
4407 MXML_DESCEND_FIRST);
4408
4409 for (type = type->child; type; type = type->next)
4410 if (!strcmp(type->value.text.string, "("))
4411 break;
4412 else
4413 {
4414 if (type->value.text.whitespace)
4415 putchar(' ');
4416
4417 write_string(stdout, type->value.text.string, OUTPUT_MAN);
4418 }
4419
4420 if (type)
4421 {
4422 /*
4423 * Output function type...
4424 */
4425
4426 printf(" (*%s", name);
4427
4428 for (type = type->next->next; type; type = type->next)
4429 {
4430 if (type->value.text.whitespace)
4431 putchar(' ');
4432
4433 write_string(stdout, type->value.text.string, OUTPUT_MAN);
4434 }
4435
4436 puts(";");
4437 }
4438 else
4439 printf(" %s;\n", name);
4440
4441 puts(".fi");
4442
4443 write_description(stdout, description, NULL, 0);
4444 }
4445 }
4446
4447 /*
4448 * List of unions...
4449 */
4450
4451 if (find_public(doc, doc, "union"))
4452 {
4453 puts(".SH UNIONS");
4454
4455 for (scut = find_public(doc, doc, "union");
4456 scut;
4457 scut = find_public(scut, doc, "union"))
4458 {
4459 name = mxmlElementGetAttr(scut, "name");
4460 description = mxmlFindElement(scut, scut, "description", NULL,
4461 NULL, MXML_DESCEND_FIRST);
4462 printf(".SS %s\n", name);
4463
4464 write_description(stdout, description, NULL, 1);
4465
4466 printf(".PP\n"
4467 ".nf\n"
4468 "union %s\n{\n", name);
4469 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
4470 MXML_DESCEND_FIRST);
4471 arg;
4472 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
4473 MXML_NO_DESCEND))
4474 {
4475 printf(" ");
4476 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4477 NULL, MXML_DESCEND_FIRST),
4478 OUTPUT_MAN);
4479 printf("%s;\n", mxmlElementGetAttr(arg, "name"));
4480 }
4481
4482 puts("};\n"
4483 ".fi");
4484
4485 write_description(stdout, description, NULL, 0);
4486 }
4487 }
4488
4489 /*
4490 * Variables...
4491 */
4492
4493 if (find_public(doc, doc, "variable"))
4494 {
4495 puts(".SH VARIABLES");
4496
4497 for (arg = find_public(doc, doc, "variable");
4498 arg;
4499 arg = find_public(arg, doc, "variable"))
4500 {
4501 name = mxmlElementGetAttr(arg, "name");
4502 description = mxmlFindElement(arg, arg, "description", NULL,
4503 NULL, MXML_DESCEND_FIRST);
4504 printf(".SS %s\n", name);
4505
4506 write_description(stdout, description, NULL, 1);
4507
4508 puts(".PP\n"
4509 ".nf");
4510
4511 write_element(stdout, doc, mxmlFindElement(arg, arg, "type", NULL,
4512 NULL, MXML_DESCEND_FIRST),
4513 OUTPUT_MAN);
4514 fputs(mxmlElementGetAttr(arg, "name"), stdout);
4515 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
4516 printf(" %s", defval);
4517 puts(";\n"
4518 ".fi");
4519
4520 write_description(stdout, description, NULL, 0);
4521 }
4522 }
4523
4524 if (footerfile)
4525 {
4526 /*
4527 * Use custom footer...
4528 */
4529
4530 write_file(stdout, footerfile);
4531 }
4532}
4533
4534
4535/*
4536 * 'write_scu()' - Write a structure, class, or union.
4537 */
4538
4539static void
4540write_scu(FILE *out, /* I - Output file */
4541 mxml_node_t *doc, /* I - Document */
4542 mxml_node_t *scut) /* I - Structure, class, or union */
4543{
4544 int i; /* Looping var */
4545 mxml_node_t *function, /* Current function */
4546 *arg, /* Current argument */
4547 *description, /* Description of function/var */
4548 *type; /* Type for argument */
4549 const char *name, /* Name of function/type */
4550 *cname, /* Class name */
4551 *defval, /* Default value */
4552 *parent, /* Parent class */
4553 *scope; /* Scope for variable/function */
4554 int inscope, /* Variable/method scope */
4555 maxscope; /* Maximum scope */
4556 char prefix; /* Prefix character */
4557 static const char * const scopes[] = /* Scope strings */
4558 {
4559 "private",
4560 "protected",
4561 "public"
4562 };
4563
4564
4565 cname = mxmlElementGetAttr(scut, "name");
4566 description = mxmlFindElement(scut, scut, "description", NULL,
4567 NULL, MXML_DESCEND_FIRST);
4568
4569 fprintf(out, "<h3 class=\"%s\">%s<a name=\"%s\">%s</a></h3>\n",
4570 scut->value.element.name, get_comment_info(description), cname,
4571 cname);
4572
4573 if (description)
4574 write_description(out, description, "p", 1);
4575
4576 fprintf(out, "<p class=\"code\">%s %s", scut->value.element.name, cname);
4577 if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL)
4578 fprintf(out, " %s", parent);
4579 fputs(" {<br>\n", out);
4580
4581 maxscope = !strcmp(scut->value.element.name, "class") ? 3 : 1;
4582
4583 for (i = 0; i < maxscope; i ++)
4584 {
4585 inscope = maxscope == 1;
4586
4587 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
4588 MXML_DESCEND_FIRST);
4589 arg;
4590 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
4591 MXML_NO_DESCEND))
4592 {
4593 if (maxscope > 1 &&
4594 ((scope = mxmlElementGetAttr(arg, "scope")) == NULL ||
4595 strcmp(scope, scopes[i])))
4596 continue;
4597
4598 if (!inscope)
4599 {
4600 inscope = 1;
4601 fprintf(out, "&nbsp;&nbsp;%s:<br>\n", scopes[i]);
4602 }
4603
4604 fputs("&nbsp;&nbsp;&nbsp;&nbsp;", out);
4605 write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
4606 NULL, MXML_DESCEND_FIRST),
4607 OUTPUT_HTML);
4608 fprintf(out, "%s;<br>\n", mxmlElementGetAttr(arg, "name"));
4609 }
4610
4611 for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
4612 MXML_DESCEND_FIRST);
4613 function;
4614 function = mxmlFindElement(function, scut, "function", NULL, NULL,
4615 MXML_NO_DESCEND))
4616 {
4617 if (maxscope > 1 &&
4618 ((scope = mxmlElementGetAttr(arg, "scope")) == NULL ||
4619 strcmp(scope, scopes[i])))
4620 continue;
4621
4622 if (!inscope)
4623 {
4624 inscope = 1;
4625 fprintf(out, "&nbsp;&nbsp;%s:<br>\n", scopes[i]);
4626 }
4627
4628 name = mxmlElementGetAttr(function, "name");
4629
4630 fputs("&nbsp;&nbsp;&nbsp;&nbsp;", out);
4631
4632 arg = mxmlFindElement(function, function, "returnvalue", NULL,
4633 NULL, MXML_DESCEND_FIRST);
4634
4635 if (arg)
4636 write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
4637 NULL, MXML_DESCEND_FIRST),
4638 OUTPUT_HTML);
4639 else if (strcmp(cname, name) && strcmp(cname, name + 1))
4640 fputs("void ", out);
4641
4642 fprintf(out, "<a href=\"#%s.%s\">%s</a>", cname, name, name);
4643
4644 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
4645 MXML_DESCEND_FIRST), prefix = '(';
4646 arg;
4647 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
4648 MXML_NO_DESCEND), prefix = ',')
4649 {
4650 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
4651 MXML_DESCEND_FIRST);
4652
4653 putc(prefix, out);
4654 if (prefix == ',')
4655 putc(' ', out);
4656
4657 if (type->child)
4658 write_element(out, doc, type, OUTPUT_HTML);
4659
4660 fputs(mxmlElementGetAttr(arg, "name"), out);
4661 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
4662 fprintf(out, " %s", defval);
4663 }
4664
4665 if (prefix == '(')
4666 fputs("(void);<br>\n", out);
4667 else
4668 fputs(");<br>\n", out);
4669 }
4670 }
4671
4672 fputs("};</p>\n"
4673 "<h4 class=\"members\">Members</h4>\n"
4674 "<dl>\n", out);
4675
4676 for (arg = mxmlFindElement(scut, scut, "variable", NULL, NULL,
4677 MXML_DESCEND_FIRST);
4678 arg;
4679 arg = mxmlFindElement(arg, scut, "variable", NULL, NULL,
4680 MXML_NO_DESCEND))
4681 {
4682 description = mxmlFindElement(arg, arg, "description", NULL,
4683 NULL, MXML_DESCEND_FIRST);
4684
4685 fprintf(out, "<dt>%s %s</dt>\n",
4686 mxmlElementGetAttr(arg, "name"), get_comment_info(description));
4687
4688 write_description(out, description, "dd", 1);
4689 write_description(out, description, "dd", 0);
4690 }
4691
4692 fputs("</dl>\n", out);
4693
4694 for (function = mxmlFindElement(scut, scut, "function", NULL, NULL,
4695 MXML_DESCEND_FIRST);
4696 function;
4697 function = mxmlFindElement(function, scut, "function", NULL, NULL,
4698 MXML_NO_DESCEND))
4699 {
4700 write_function(out, doc, function, 4);
4701 }
4702}
4703
4704
4705/*
4706 * 'write_string()' - Write a string, quoting HTML special chars as needed.
4707 */
4708
4709static void
4710write_string(FILE *out, /* I - Output file */
4711 const char *s, /* I - String to write */
4712 int mode) /* I - Output mode */
4713{
4714 switch (mode)
4715 {
4716 case OUTPUT_HTML :
4717 case OUTPUT_XML :
4718 while (*s)
4719 {
4720 if (*s == '&')
4721 fputs("&amp;", out);
4722 else if (*s == '<')
4723 fputs("&lt;", out);
4724 else if (*s == '>')
4725 fputs("&gt;", out);
4726 else if (*s == '\"')
4727 fputs("&quot;", out);
4728 else if (*s & 128)
4729 {
4730 /*
4731 * Convert UTF-8 to Unicode constant...
4732 */
4733
4734 int ch; /* Unicode character */
4735
4736
4737 ch = *s & 255;
4738
4739 if ((ch & 0xe0) == 0xc0)
4740 {
4741 ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
4742 s ++;
4743 }
4744 else if ((ch & 0xf0) == 0xe0)
4745 {
4746 ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
4747 s += 2;
4748 }
4749
4750 if (ch == 0xa0)
4751 {
4752 /*
4753 * Handle non-breaking space as-is...
4754 */
4755
4756 fputs("&nbsp;", out);
4757 }
4758 else
4759 fprintf(out, "&#x%x;", ch);
4760 }
4761 else
4762 putc(*s, out);
4763
4764 s ++;
4765 }
4766 break;
4767
4768 case OUTPUT_MAN :
4769 while (*s)
4770 {
4771 if (*s == '\\' || *s == '-')
4772 putc('\\', out);
4773
4774 putc(*s++, out);
4775 }
4776 break;
4777 }
4778}
4779
4780
4781/*
4782 * 'write_toc()' - Write a table-of-contents.
4783 */
4784
4785static void
4786write_toc(FILE *out, /* I - Output file */
4787 mxml_node_t *doc, /* I - Document */
4788 const char *introfile, /* I - Introduction file */
4789 const char *target, /* I - Target name */
4790 int xml) /* I - Write XML nodes? */
4791{
4792 FILE *fp; /* Intro file */
4793 mxml_node_t *function, /* Current function */
4794 *scut, /* Struct/class/union/typedef */
4795 *arg, /* Current argument */
4796 *description; /* Description of function/var */
4797 const char *name, /* Name of function/type */
4798 *targetattr; /* Target attribute, if any */
4799 int xmlid = 1; /* Current XML node ID */
4800
4801
4802 /*
4803 * If target is set, it is the frame file that contains the body.
4804 * Otherwise, we are creating a single-file...
4805 */
4806
4807 if (target)
4808 targetattr = " target=\"body\"";
4809 else
4810 targetattr = "";
4811
4812 /*
4813 * The table-of-contents is a nested unordered list. Start by
4814 * reading any intro file to see if there are any headings there.
4815 */
4816
4817 if (!xml)
4818 fputs("<h2 class=\"title\">Contents</h2>\n"
4819 "<ul class=\"contents\">\n", out);
4820
4821 if (introfile && (fp = fopen(introfile, "r")) != NULL)
4822 {
4823 char line[8192], /* Line from file */
4824 *ptr, /* Pointer in line */
4825 *end, /* End of line */
4826 *anchor, /* Anchor name */
4827 quote, /* Quote character for value */
4828 level = '2', /* Current heading level */
4829 newlevel; /* New heading level */
4830 int inelement; /* In an element? */
4831
4832
4833 while (fgets(line, sizeof(line), fp))
4834 {
4835 /*
4836 * See if this line has a heading...
4837 */
4838
4839 if ((ptr = strstr(line, "<h")) == NULL &&
4840 (ptr = strstr(line, "<H")) == NULL)
4841 continue;
4842
4843 if (ptr[2] != '2' && ptr[2] != '3')
4844 continue;
4845
4846 newlevel = ptr[2];
4847
4848 /*
4849 * Make sure we have the whole heading...
4850 */
4851
4852 while (!strstr(line, "</h") && !strstr(line, "</H"))
4853 {
4854 end = line + strlen(line);
4855
4856 if (end == (line + sizeof(line) - 1) ||
4857 !fgets(end, (int)(sizeof(line) - (end - line)), fp))
4858 break;
4859 }
4860
4861 /*
4862 * Convert newlines and tabs to spaces...
4863 */
4864
4865 for (ptr = line; *ptr; ptr ++)
4866 if (isspace(*ptr & 255))
4867 *ptr = ' ';
4868
4869 /*
4870 * Find the anchor and text...
4871 */
4872
4873 for (ptr = strchr(line, '<'); ptr; ptr = strchr(ptr + 1, '<'))
4874 if (!strncmp(ptr, "<A NAME=", 8) || !strncmp(ptr, "<a name=", 8))
4875 break;
4876
4877 if (!ptr)
4878 continue;
4879
4880 ptr += 8;
4881 inelement = 1;
4882
4883 if (*ptr == '\'' || *ptr == '\"')
4884 {
4885 /*
4886 * Quoted anchor...
4887 */
4888
4889 quote = *ptr++;
4890 anchor = ptr;
4891
4892 while (*ptr && *ptr != quote)
4893 ptr ++;
4894
4895 if (!*ptr)
4896 continue;
4897
4898 *ptr++ = '\0';
4899 }
4900 else
4901 {
4902 /*
4903 * Non-quoted anchor...
4904 */
4905
4906 anchor = ptr;
4907
4908 while (*ptr && *ptr != '>' && !isspace(*ptr & 255))
4909 ptr ++;
4910
4911 if (!*ptr)
4912 continue;
4913
4914 if (*ptr == '>')
4915 inelement = 0;
4916
4917 *ptr++ = '\0';
4918 }
4919
4920 /*
4921 * Write text until we see "</A>"...
4922 */
4923
4924 if (xml)
4925 {
4926 if (newlevel < level)
4927 fputs("</Node>\n"
4928 "</Subnodes></Node>\n", out);
4929 else if (newlevel > level && newlevel == '3')
4930 fputs("<Subnodes>\n", out);
4931 else if (xmlid > 1)
4932 fputs("</Node>\n", out);
4933
4934 level = newlevel;
4935
4936 fprintf(out, "<Node id=\"%d\">\n"
4937 "<Path>Documentation/index.html</Path>\n"
4938 "<Anchor>%s</Anchor>\n"
4939 "<Name>", xmlid ++, anchor);
4940
4941 quote = 0;
4942
4943 while (*ptr)
4944 {
4945 if (inelement)
4946 {
4947 if (*ptr == quote)
4948 quote = 0;
4949 else if (*ptr == '>')
4950 inelement = 0;
4951 else if (*ptr == '\'' || *ptr == '\"')
4952 quote = *ptr;
4953 }
4954 else if (*ptr == '<')
4955 {
4956 if (!strncmp(ptr, "</A>", 4) || !strncmp(ptr, "</a>", 4))
4957 break;
4958
4959 inelement = 1;
4960 }
4961 else
4962 putc(*ptr, out);
4963
4964 ptr ++;
4965 }
4966
4967 fputs("</Name>\n", out);
4968 }
4969 else
4970 {
4971 if (newlevel < level)
4972 fputs("</li>\n"
4973 "</ul></li>\n", out);
4974 else if (newlevel > level)
4975 fputs("<ul class=\"subcontents\">\n", out);
4976 else if (xmlid > 1)
4977 fputs("</li>\n", out);
4978
4979 level = newlevel;
4980 xmlid ++;
4981
4982 fprintf(out, "%s<li><a href=\"%s#%s\"%s>", level > '2' ? "\t" : "",
4983 target ? target : "", anchor, targetattr);
4984
4985 quote = 0;
4986
4987 while (*ptr)
4988 {
4989 if (inelement)
4990 {
4991 if (*ptr == quote)
4992 quote = 0;
4993 else if (*ptr == '>')
4994 inelement = 0;
4995 else if (*ptr == '\'' || *ptr == '\"')
4996 quote = *ptr;
4997 }
4998 else if (*ptr == '<')
4999 {
5000 if (!strncmp(ptr, "</A>", 4) || !strncmp(ptr, "</a>", 4))
5001 break;
5002
5003 inelement = 1;
5004 }
5005 else
5006 putc(*ptr, out);
5007
5008 ptr ++;
5009 }
5010
5011 fputs("</a>", out);
5012 }
5013 }
5014
5015 if (level > '1')
5016 {
5017 if (xml)
5018 {
5019 fputs("</Node>\n", out);
5020
5021 if (level == '3')
5022 fputs("</Subnodes></Node>\n", out);
5023 }
5024 else
5025 {
5026 fputs("</li>\n", out);
5027
5028 if (level == '3')
5029 fputs("</ul></li>\n", out);
5030 }
5031 }
5032
5033 fclose(fp);
5034 }
5035
5036 /*
5037 * Next the classes...
5038 */
5039
5040 if ((scut = find_public(doc, doc, "class")) != NULL)
5041 {
5042 if (xml)
5043 fprintf(out, "<Node id=\"%d\">\n"
5044 "<Path>Documentation/index.html</Path>\n"
5045 "<Anchor>CLASSES</Anchor>\n"
5046 "<Name>Classes</Name>\n"
5047 "<Subnodes>\n", xmlid ++);
5048 else
5049 fprintf(out, "<li><a href=\"%s#CLASSES\"%s>Classes</a>"
5050 "<ul class=\"code\">\n",
5051 target ? target : "", targetattr);
5052
5053 while (scut)
5054 {
5055 name = mxmlElementGetAttr(scut, "name");
5056 description = mxmlFindElement(scut, scut, "description",
5057 NULL, NULL, MXML_DESCEND_FIRST);
5058
5059 if (xml)
5060 {
5061 fprintf(out, "<Node id=\"%d\">\n"
5062 "<Path>Documentation/index.html</Path>\n"
5063 "<Anchor>%s</Anchor>\n"
5064 "<Name>%s</Name>\n"
5065 "</Node>\n", xmlid ++, name, name);
5066 }
5067 else
5068 {
5069 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5070 target ? target : "", name, targetattr);
5071 write_description(out, description, "", 1);
5072 fprintf(out, "\">%s</a></li>\n", name);
5073 }
5074
5075 scut = find_public(scut, doc, "class");
5076 }
5077
5078 if (xml)
5079 fputs("</Subnodes></Node>\n", out);
5080 else
5081 fputs("</ul></li>\n", out);
5082 }
5083
5084 /*
5085 * Functions...
5086 */
5087
5088 if ((function = find_public(doc, doc, "function")) != NULL)
5089 {
5090 if (xml)
5091 fprintf(out, "<Node id=\"%d\">\n"
5092 "<Path>Documentation/index.html</Path>\n"
5093 "<Anchor>FUNCTIONS</Anchor>\n"
5094 "<Name>Functions</Name>\n"
5095 "<Subnodes>\n", xmlid ++);
5096 else
5097 fprintf(out, "<li><a href=\"%s#FUNCTIONS\"%s>Functions</a>"
5098 "<ul class=\"code\">\n", target ? target : "", targetattr);
5099
5100 while (function)
5101 {
5102 name = mxmlElementGetAttr(function, "name");
5103 description = mxmlFindElement(function, function, "description",
5104 NULL, NULL, MXML_DESCEND_FIRST);
5105
5106 if (xml)
5107 {
5108 fprintf(out, "<Node id=\"%d\">\n"
5109 "<Path>Documentation/index.html</Path>\n"
5110 "<Anchor>%s</Anchor>\n"
5111 "<Name>%s</Name>\n"
5112 "</Node>\n", xmlid ++, name, name);
5113 }
5114 else
5115 {
5116 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5117 target ? target : "", name, targetattr);
5118 write_description(out, description, "", 1);
5119 fprintf(out, "\">%s</a></li>\n", name);
5120 }
5121
5122 function = find_public(function, doc, "function");
5123 }
5124
5125 if (xml)
5126 fputs("</Subnodes></Node>\n", out);
5127 else
5128 fputs("</ul></li>\n", out);
5129 }
5130
5131 /*
5132 * Data types...
5133 */
5134
5135 if ((scut = find_public(doc, doc, "typedef")) != NULL)
5136 {
5137 if (xml)
5138 fprintf(out, "<Node id=\"%d\">\n"
5139 "<Path>Documentation/index.html</Path>\n"
5140 "<Anchor>TYPES</Anchor>\n"
5141 "<Name>Data Types</Name>\n"
5142 "<Subnodes>\n", xmlid ++);
5143 else
5144 fprintf(out, "<li><a href=\"%s#TYPES\"%s>Data Types</a>"
5145 "<ul class=\"code\">\n", target ? target : "", targetattr);
5146
5147 while (scut)
5148 {
5149 name = mxmlElementGetAttr(scut, "name");
5150 description = mxmlFindElement(scut, scut, "description",
5151 NULL, NULL, MXML_DESCEND_FIRST);
5152
5153 if (xml)
5154 {
5155 fprintf(out, "<Node id=\"%d\">\n"
5156 "<Path>Documentation/index.html</Path>\n"
5157 "<Anchor>%s</Anchor>\n"
5158 "<Name>%s</Name>\n"
5159 "</Node>\n", xmlid ++, name, name);
5160 }
5161 else
5162 {
5163 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5164 target ? target : "", name, targetattr);
5165 write_description(out, description, "", 1);
5166 fprintf(out, "\">%s</a></li>\n", name);
5167 }
5168
5169 scut = find_public(scut, doc, "typedef");
5170 }
5171
5172 if (xml)
5173 fputs("</Subnodes></Node>\n", out);
5174 else
5175 fputs("</ul></li>\n", out);
5176 }
5177
5178 /*
5179 * Structures...
5180 */
5181
5182 if ((scut = find_public(doc, doc, "struct")) != NULL)
5183 {
5184 if (xml)
5185 fprintf(out, "<Node id=\"%d\">\n"
5186 "<Path>Documentation/index.html</Path>\n"
5187 "<Anchor>STRUCTURES</Anchor>\n"
5188 "<Name>Structures</Name>\n"
5189 "<Subnodes>\n", xmlid ++);
5190 else
5191 fprintf(out, "<li><a href=\"%s#STRUCTURES\"%s>Structures</a>"
5192 "<ul class=\"code\">\n", target ? target : "", targetattr);
5193
5194 while (scut)
5195 {
5196 name = mxmlElementGetAttr(scut, "name");
5197 description = mxmlFindElement(scut, scut, "description",
5198 NULL, NULL, MXML_DESCEND_FIRST);
5199
5200 if (xml)
5201 {
5202 fprintf(out, "<Node id=\"%d\">\n"
5203 "<Path>Documentation/index.html</Path>\n"
5204 "<Anchor>%s</Anchor>\n"
5205 "<Name>%s</Name>\n"
5206 "</Node>\n", xmlid ++, name, name);
5207 }
5208 else
5209 {
5210 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5211 target ? target : "", name, targetattr);
5212 write_description(out, description, "", 1);
5213 fprintf(out, "\">%s</a></li>\n", name);
5214 }
5215
5216 scut = find_public(scut, doc, "struct");
5217 }
5218
5219 if (xml)
5220 fputs("</Subnodes></Node>\n", out);
5221 else
5222 fputs("</ul></li>\n", out);
5223 }
5224
5225 /*
5226 * Unions...
5227 */
5228
5229 if ((scut = find_public(doc, doc, "union")) != NULL)
5230 {
5231 if (xml)
5232 fprintf(out, "<Node id=\"%d\">\n"
5233 "<Path>Documentation/index.html</Path>\n"
5234 "<Anchor>UNIONS</Anchor>\n"
5235 "<Name>Unions</Name>\n"
5236 "<Subnodes>\n", xmlid ++);
5237 else
5238 fprintf(out,
5239 "<li><a href=\"%s#UNIONS\"%s>Unions</a><ul class=\"code\">\n",
5240 target ? target : "", targetattr);
5241
5242 while (scut)
5243 {
5244 name = mxmlElementGetAttr(scut, "name");
5245 description = mxmlFindElement(scut, scut, "description",
5246 NULL, NULL, MXML_DESCEND_FIRST);
5247
5248 if (xml)
5249 {
5250 fprintf(out, "<Node id=\"%d\">\n"
5251 "<Path>Documentation/index.html</Path>\n"
5252 "<Anchor>%s</Anchor>\n"
5253 "<Name>%s</Name>\n"
5254 "</Node>\n", xmlid ++, name, name);
5255 }
5256 else
5257 {
5258 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5259 target ? target : "", name, targetattr);
5260 write_description(out, description, "", 1);
5261 fprintf(out, "\">%s</a></li>\n", name);
5262 }
5263
5264 scut = find_public(scut, doc, "union");
5265 }
5266
5267 if (xml)
5268 fputs("</Subnodes></Node>\n", out);
5269 else
5270 fputs("</ul></li>\n", out);
5271 }
5272
5273 /*
5274 * Globals variables...
5275 */
5276
5277 if ((arg = find_public(doc, doc, "variable")) != NULL)
5278 {
5279 if (xml)
5280 fprintf(out, "<Node id=\"%d\">\n"
5281 "<Path>Documentation/index.html</Path>\n"
5282 "<Anchor>VARIABLES</Anchor>\n"
5283 "<Name>Variables</Name>\n"
5284 "<Subnodes>\n", xmlid ++);
5285 else
5286 fprintf(out, "<li><a href=\"%s#VARIABLES\"%s>Variables</a>"
5287 "<ul class=\"code\">\n", target ? target : "", targetattr);
5288
5289 while (arg)
5290 {
5291 name = mxmlElementGetAttr(arg, "name");
5292 description = mxmlFindElement(arg, arg, "description",
5293 NULL, NULL, MXML_DESCEND_FIRST);
5294
5295 if (xml)
5296 {
5297 fprintf(out, "<Node id=\"%d\">\n"
5298 "<Path>Documentation/index.html</Path>\n"
5299 "<Anchor>%s</Anchor>\n"
5300 "<Name>%s</Name>\n"
5301 "</Node>\n", xmlid ++, name, name);
5302 }
5303 else
5304 {
5305 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5306 target ? target : "", name, targetattr);
5307 write_description(out, description, "", 1);
5308 fprintf(out, "\">%s</a></li>\n", name);
5309 }
5310
5311 arg = find_public(arg, doc, "variable");
5312 }
5313
5314 if (xml)
5315 fputs("</Subnodes></Node>\n", out);
5316 else
5317 fputs("</ul></li>\n", out);
5318 }
5319
5320 /*
5321 * Enumerations/constants...
5322 */
5323
5324 if ((scut = find_public(doc, doc, "enumeration")) != NULL)
5325 {
5326 if (xml)
5327 fprintf(out, "<Node id=\"%d\">\n"
5328 "<Path>Documentation/index.html</Path>\n"
5329 "<Anchor>ENUMERATIONS</Anchor>\n"
5330 "<Name>Constants</Name>\n"
5331 "<Subnodes>\n", xmlid ++);
5332 else
5333 fprintf(out, "<li><a href=\"%s#ENUMERATIONS\"%s>Constants</a>"
5334 "<ul class=\"code\">\n", target ? target : "", targetattr);
5335
5336 while (scut)
5337 {
5338 name = mxmlElementGetAttr(scut, "name");
5339 description = mxmlFindElement(scut, scut, "description",
5340 NULL, NULL, MXML_DESCEND_FIRST);
5341
5342 if (xml)
5343 {
5344 fprintf(out, "<Node id=\"%d\">\n"
5345 "<Path>Documentation/index.html</Path>\n"
5346 "<Anchor>%s</Anchor>\n"
5347 "<Name>%s</Name>\n"
5348 "</Node>\n", xmlid ++, name, name);
5349 }
5350 else
5351 {
5352 fprintf(out, "\t<li><a href=\"%s#%s\"%s title=\"",
5353 target ? target : "", name, targetattr);
5354 write_description(out, description, "", 1);
5355 fprintf(out, "\">%s</a></li>\n", name);
5356 }
5357
5358 scut = find_public(scut, doc, "enumeration");
5359 }
5360
5361 if (xml)
5362 fputs("</Subnodes></Node>\n", out);
5363 else
5364 fputs("</ul></li>\n", out);
5365 }
5366
5367 /*
5368 * Close out the HTML table-of-contents list as needed...
5369 */
5370
5371 if (!xml)
5372 fputs("</ul>\n", out);
5373}
5374
5375
5376/*
5377 * 'write_tokens()' - Write <Token> nodes for all APIs.
5378 */
5379
5380static void
5381write_tokens(FILE *out, /* I - Output file */
5382 mxml_node_t *doc, /* I - Document */
5383 const char *path) /* I - Path to help file */
5384{
5385 mxml_node_t *function, /* Current function */
5386 *scut, /* Struct/class/union/typedef */
5387 *arg, /* Current argument */
5388 *description, /* Description of function/var */
5389 *type, /* Type node */
5390 *node; /* Current child node */
5391 const char *name, /* Name of function/type */
5392 *cename, /* Current class/enum name */
5393 *defval; /* Default value for argument */
5394 char prefix; /* Prefix for declarations */
5395
5396
5397 /*
5398 * Classes...
5399 */
5400
5401 if ((scut = find_public(doc, doc, "class")) != NULL)
5402 {
5403 while (scut)
5404 {
5405 cename = mxmlElementGetAttr(scut, "name");
5406 description = mxmlFindElement(scut, scut, "description",
5407 NULL, NULL, MXML_DESCEND_FIRST);
5408
5409 fprintf(out, "<Token>\n"
5410 "<Path>Documentation/%s</Path>\n"
5411 "<Anchor>%s</Anchor>\n"
5412 "<TokenIdentifier>//apple_ref/cpp/cl/%s</TokenIdentifier>\n"
5413 "<Abstract>", path, cename, cename);
5414 write_description(out, description, "", 1);
5415 fputs("</Abstract>\n"
5416 "</Token>\n", out);
5417
5418 if ((function = find_public(scut, scut, "function")) != NULL)
5419 {
5420 while (function)
5421 {
5422 name = mxmlElementGetAttr(function, "name");
5423 description = mxmlFindElement(function, function, "description",
5424 NULL, NULL, MXML_DESCEND_FIRST);
5425
5426 fprintf(out, "<Token>\n"
5427 "<Path>Documentation/%s</Path>\n"
5428 "<Anchor>%s.%s</Anchor>\n"
5429 "<TokenIdentifier>//apple_ref/cpp/clm/%s/%s", path,
5430 cename, name, cename, name);
5431
5432 arg = mxmlFindElement(function, function, "returnvalue", NULL,
5433 NULL, MXML_DESCEND_FIRST);
5434
5435 if (arg && (type = mxmlFindElement(arg, arg, "type", NULL,
5436 NULL, MXML_DESCEND_FIRST)) != NULL)
5437 {
5438 for (node = type->child; node; node = node->next)
5439 fputs(node->value.text.string, out);
5440 }
5441 else if (strcmp(cename, name) && strcmp(cename, name + 1))
5442 fputs("void", out);
5443
5444 fputs("/", out);
5445
5446 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
5447 MXML_DESCEND_FIRST), prefix = '(';
5448 arg;
5449 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
5450 MXML_NO_DESCEND), prefix = ',')
5451 {
5452 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
5453 MXML_DESCEND_FIRST);
5454
5455 putc(prefix, out);
5456
5457 for (node = type->child; node; node = node->next)
5458 fputs(node->value.text.string, out);
5459
5460 fputs(mxmlElementGetAttr(arg, "name"), out);
5461 }
5462
5463 if (prefix == '(')
5464 fputs("(void", out);
5465
5466 fputs(")</TokenIdentifier>\n"
5467 "<Abstract>", out);
5468 write_description(out, description, "", 1);
5469 fputs("</Abstract>\n"
5470 "<Declaration>", out);
5471
5472 arg = mxmlFindElement(function, function, "returnvalue", NULL,
5473 NULL, MXML_DESCEND_FIRST);
5474
5475 if (arg)
5476 write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
5477 NULL, MXML_DESCEND_FIRST),
5478 OUTPUT_XML);
5479 else if (strcmp(cename, name) && strcmp(cename, name + 1))
5480 fputs("void ", out);
5481
5482 fputs(name, out);
5483
5484 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
5485 MXML_DESCEND_FIRST), prefix = '(';
5486 arg;
5487 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
5488 MXML_NO_DESCEND), prefix = ',')
5489 {
5490 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
5491 MXML_DESCEND_FIRST);
5492
5493 putc(prefix, out);
5494 if (prefix == ',')
5495 putc(' ', out);
5496
5497 if (type->child)
5498 write_element(out, doc, type, OUTPUT_XML);
5499
5500 fputs(mxmlElementGetAttr(arg, "name"), out);
5501 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
5502 fprintf(out, " %s", defval);
5503 }
5504
5505 if (prefix == '(')
5506 fputs("(void);", out);
5507 else
5508 fputs(");", out);
5509
5510 fputs("</Declaration>\n"
5511 "</Token>\n", out);
5512
5513 function = find_public(function, doc, "function");
5514 }
5515 }
5516 scut = find_public(scut, doc, "class");
5517 }
5518 }
5519
5520 /*
5521 * Functions...
5522 */
5523
5524 if ((function = find_public(doc, doc, "function")) != NULL)
5525 {
5526 while (function)
5527 {
5528 name = mxmlElementGetAttr(function, "name");
5529 description = mxmlFindElement(function, function, "description",
5530 NULL, NULL, MXML_DESCEND_FIRST);
5531
5532 fprintf(out, "<Token>\n"
5533 "<Path>Documentation/%s</Path>\n"
5534 "<Anchor>%s</Anchor>\n"
5535 "<TokenIdentifier>//apple_ref/c/func/%s</TokenIdentifier>\n"
5536 "<Abstract>", path, name, name);
5537 write_description(out, description, "", 1);
5538 fputs("</Abstract>\n"
5539 "<Declaration>", out);
5540
5541 arg = mxmlFindElement(function, function, "returnvalue", NULL,
5542 NULL, MXML_DESCEND_FIRST);
5543
5544 if (arg)
5545 write_element(out, doc, mxmlFindElement(arg, arg, "type", NULL,
5546 NULL, MXML_DESCEND_FIRST),
5547 OUTPUT_XML);
5548 else // if (strcmp(cname, name) && strcmp(cname, name + 1))
5549 fputs("void ", out);
5550
5551 fputs(name, out);
5552
5553 for (arg = mxmlFindElement(function, function, "argument", NULL, NULL,
5554 MXML_DESCEND_FIRST), prefix = '(';
5555 arg;
5556 arg = mxmlFindElement(arg, function, "argument", NULL, NULL,
5557 MXML_NO_DESCEND), prefix = ',')
5558 {
5559 type = mxmlFindElement(arg, arg, "type", NULL, NULL,
5560 MXML_DESCEND_FIRST);
5561
5562 putc(prefix, out);
5563 if (prefix == ',')
5564 putc(' ', out);
5565
5566 if (type->child)
5567 write_element(out, doc, type, OUTPUT_XML);
5568
5569 fputs(mxmlElementGetAttr(arg, "name"), out);
5570 if ((defval = mxmlElementGetAttr(arg, "default")) != NULL)
5571 fprintf(out, " %s", defval);
5572 }
5573
5574 if (prefix == '(')
5575 fputs("(void);", out);
5576 else
5577 fputs(");", out);
5578
5579 fputs("</Declaration>\n"
5580 "</Token>\n", out);
5581
5582 function = find_public(function, doc, "function");
5583 }
5584 }
5585
5586 /*
5587 * Data types...
5588 */
5589
5590 if ((scut = find_public(doc, doc, "typedef")) != NULL)
5591 {
5592 while (scut)
5593 {
5594 name = mxmlElementGetAttr(scut, "name");
5595 description = mxmlFindElement(scut, scut, "description",
5596 NULL, NULL, MXML_DESCEND_FIRST);
5597
5598 fprintf(out, "<Token>\n"
5599 "<Path>Documentation/%s</Path>\n"
5600 "<Anchor>%s</Anchor>\n"
5601 "<TokenIdentifier>//apple_ref/c/tdef/%s</TokenIdentifier>\n"
5602 "<Abstract>", path, name, name);
5603 write_description(out, description, "", 1);
5604 fputs("</Abstract>\n"
5605 "</Token>\n", out);
5606
5607 scut = find_public(scut, doc, "typedef");
5608 }
5609 }
5610
5611 /*
5612 * Structures...
5613 */
5614
5615 if ((scut = find_public(doc, doc, "struct")) != NULL)
5616 {
5617 while (scut)
5618 {
5619 name = mxmlElementGetAttr(scut, "name");
5620 description = mxmlFindElement(scut, scut, "description",
5621 NULL, NULL, MXML_DESCEND_FIRST);
5622
5623 fprintf(out, "<Token>\n"
5624 "<Path>Documentation/%s</Path>\n"
5625 "<Anchor>%s</Anchor>\n"
5626 "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
5627 "<Abstract>", path, name, name);
5628 write_description(out, description, "", 1);
5629 fputs("</Abstract>\n"
5630 "</Token>\n", out);
5631
5632 scut = find_public(scut, doc, "struct");
5633 }
5634 }
5635
5636 /*
5637 * Unions...
5638 */
5639
5640 if ((scut = find_public(doc, doc, "union")) != NULL)
5641 {
5642 while (scut)
5643 {
5644 name = mxmlElementGetAttr(scut, "name");
5645 description = mxmlFindElement(scut, scut, "description",
5646 NULL, NULL, MXML_DESCEND_FIRST);
5647
5648 fprintf(out, "<Token>\n"
5649 "<Path>Documentation/%s</Path>\n"
5650 "<Anchor>%s</Anchor>\n"
5651 "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
5652 "<Abstract>", path, name, name);
5653 write_description(out, description, "", 1);
5654 fputs("</Abstract>\n"
5655 "</Token>\n", out);
5656
5657 scut = find_public(scut, doc, "union");
5658 }
5659 }
5660
5661 /*
5662 * Globals variables...
5663 */
5664
5665 if ((arg = find_public(doc, doc, "variable")) != NULL)
5666 {
5667 while (arg)
5668 {
5669 name = mxmlElementGetAttr(arg, "name");
5670 description = mxmlFindElement(arg, arg, "description",
5671 NULL, NULL, MXML_DESCEND_FIRST);
5672
5673 fprintf(out, "<Token>\n"
5674 "<Path>Documentation/%s</Path>\n"
5675 "<Anchor>%s</Anchor>\n"
5676 "<TokenIdentifier>//apple_ref/c/data/%s</TokenIdentifier>\n"
5677 "<Abstract>", path, name, name);
5678 write_description(out, description, "", 1);
5679 fputs("</Abstract>\n"
5680 "</Token>\n", out);
5681
5682 arg = find_public(arg, doc, "variable");
5683 }
5684 }
5685
5686 /*
5687 * Enumerations/constants...
5688 */
5689
5690 if ((scut = find_public(doc, doc, "enumeration")) != NULL)
5691 {
5692 while (scut)
5693 {
5694 cename = mxmlElementGetAttr(scut, "name");
5695 description = mxmlFindElement(scut, scut, "description",
5696 NULL, NULL, MXML_DESCEND_FIRST);
5697
5698 fprintf(out, "<Token>\n"
5699 "<Path>Documentation/%s</Path>\n"
5700 "<Anchor>%s</Anchor>\n"
5701 "<TokenIdentifier>//apple_ref/c/tag/%s</TokenIdentifier>\n"
5702 "<Abstract>", path, cename, cename);
5703 write_description(out, description, "", 1);
5704 fputs("</Abstract>\n"
5705 "</Token>\n", out);
5706
5707 for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL,
5708 MXML_DESCEND_FIRST);
5709 arg;
5710 arg = mxmlFindElement(arg, scut, "constant", NULL, NULL,
5711 MXML_NO_DESCEND))
5712 {
5713 name = mxmlElementGetAttr(arg, "name");
5714 description = mxmlFindElement(arg, arg, "description", NULL,
5715 NULL, MXML_DESCEND_FIRST);
5716 fprintf(out, "<Token>\n"
5717 "<Path>Documentation/%s</Path>\n"
5718 "<Anchor>%s</Anchor>\n"
5719 "<TokenIdentifier>//apple_ref/c/econst/%s</TokenIdentifier>\n"
5720 "<Abstract>", path, cename, name);
5721 write_description(out, description, "", 1);
5722 fputs("</Abstract>\n"
5723 "</Token>\n", out);
5724 }
5725
5726 scut = find_public(scut, doc, "enumeration");
5727 }
5728 }
5729}
5730
5731
5732/*
5733 * 'ws_cb()' - Whitespace callback for saving.
5734 */
5735
5736static const char * /* O - Whitespace string or NULL for none */
5737ws_cb(mxml_node_t *node, /* I - Element node */
5738 int where) /* I - Where value */
5739{
5740 const char *name; /* Name of element */
5741 int depth; /* Depth of node */
5742 static const char *spaces = " ";
5743 /* Whitespace (40 spaces) for indent */
5744
5745
5746 name = node->value.element.name;
5747
5748 switch (where)
5749 {
5750 case MXML_WS_BEFORE_CLOSE :
5751 if (strcmp(name, "argument") &&
5752 strcmp(name, "class") &&
5753 strcmp(name, "constant") &&
5754 strcmp(name, "enumeration") &&
5755 strcmp(name, "function") &&
5756 strcmp(name, "mxmldoc") &&
5757 strcmp(name, "namespace") &&
5758 strcmp(name, "returnvalue") &&
5759 strcmp(name, "struct") &&
5760 strcmp(name, "typedef") &&
5761 strcmp(name, "union") &&
5762 strcmp(name, "variable"))
5763 return (NULL);
5764
5765 for (depth = -4; node; node = node->parent, depth += 2);
5766 if (depth > 40)
5767 return (spaces);
5768 else if (depth < 2)
5769 return (NULL);
5770 else
5771 return (spaces + 40 - depth);
5772
5773 case MXML_WS_AFTER_CLOSE :
5774 return ("\n");
5775
5776 case MXML_WS_BEFORE_OPEN :
5777 for (depth = -4; node; node = node->parent, depth += 2);
5778 if (depth > 40)
5779 return (spaces);
5780 else if (depth < 2)
5781 return (NULL);
5782 else
5783 return (spaces + 40 - depth);
5784
5785 default :
5786 case MXML_WS_AFTER_OPEN :
5787 if (strcmp(name, "argument") &&
5788 strcmp(name, "class") &&
5789 strcmp(name, "constant") &&
5790 strcmp(name, "enumeration") &&
5791 strcmp(name, "function") &&
5792 strcmp(name, "mxmldoc") &&
5793 strcmp(name, "namespace") &&
5794 strcmp(name, "returnvalue") &&
5795 strcmp(name, "struct") &&
5796 strcmp(name, "typedef") &&
5797 strcmp(name, "union") &&
5798 strcmp(name, "variable") &&
5799 strncmp(name, "?xml", 4))
5800 return (NULL);
5801 else
5802 return ("\n");
5803 }
5804}
5805
5806
5807/*
5808 * End of "$Id: mxmldoc.c 440 2011-08-11 18:51:26Z mike $".
5809 */
diff --git a/pathologist/src/pathologist/Makefile.am b/pathologist/src/pathologist/Makefile.am
new file mode 100644
index 0000000..215d892
--- /dev/null
+++ b/pathologist/src/pathologist/Makefile.am
@@ -0,0 +1,58 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage -O0
9 XLIB = -lgcov
10endif
11
12
13if !MINGW
14if HAVE_ESMTP
15if HAVE_OPENSSL
16
17bin_PROGRAMS = \
18 pathologist
19
20pathologist_SOURCES = \
21 pathologist.c \
22 getopt.c \
23 getopt_helpers.c \
24 mail_sender.c \
25 action.c \
26 xml_writer.c \
27 edb_api.c
28
29pathologist_LDADD = \
30 $(top_builddir)/src/mi/libmi.la \
31 $(top_builddir)/src/util/libpathologistutil.la \
32 -lesmtp \
33 -lsqlite3 \
34 $(XLIB) \
35 $(GN_LIBINTL)
36
37if ENABLE_TEST_RUN
38if SEASPIDER
39TESTS = $(check_PROGRAMS)
40endif
41endif
42
43check_PROGRAMS = \
44 test_pathologist
45
46test_pathologist_SOURCES = \
47 test_pathologist.c
48
49test_pathologist_LDADD = \
50 $(top_builddir)/src/minixml/libminixml.la
51
52EXTRA_DIST = \
53 ../../refs
54
55
56endif
57endif
58endif
diff --git a/pathologist/src/pathologist/action.c b/pathologist/src/pathologist/action.c
new file mode 100644
index 0000000..dcd1872
--- /dev/null
+++ b/pathologist/src/pathologist/action.c
@@ -0,0 +1,1124 @@
1
2#include "monkey_common.h"
3#include "action.h"
4#include "pathologist_edb.h"
5#include "pathologist_xml_writer.h"
6#include <libesmtp.h>
7#include <string.h>
8#include <stdio.h>
9#include <sys/stat.h>
10#include <errno.h>
11
12extern void sendMail(const char *messageContents, const char *reportFileName,
13 const char *emailAddress);
14
15static int crashExpressionFoundInEDB = MONKEY_YES;
16static int async_c = 0;
17static int stoppedInSharedLib = MONKEY_NO;
18static int failureFunctionStartLine = 0; // start line number of the function in which the failure occurs
19static struct WatchInfo *watchInfoListHead = NULL;
20static struct WatchInfo *watchInfoListTail = NULL;
21static struct FileName *fileNameListHead = NULL;
22static struct FileName *fileNameListTail = NULL;
23static struct ScopeEnd *scopeEndListHead = NULL;
24static struct ScopeEnd *scopeEndListTail = NULL;
25
26
27struct ScopeEnd {
28 struct ScopeEnd *next;
29 struct ScopeEnd *prev;
30
31 int lineNo;
32};
33
34
35struct FileName {
36 struct FileName *next;
37 struct FileName *prev;
38
39 const char *name;
40};
41
42
43struct Expression {
44 struct Expression *next;
45 struct Expression *prev;
46 const char *expressionSyntax;
47 const char *expressionValue;
48 int isCall;
49};
50
51
52struct Function {
53 struct Function *next;
54 struct Function *prev;
55 const char *name;
56 const char *file;
57 int line;
58 int depth;
59 struct Expression *expressionListHead;
60 struct Expression *expressionListTail;
61};
62
63struct Trace {
64 struct Trace *next;
65 struct Trace *prev;
66 struct Function *functionListHead;
67 struct Function *functionListTail;
68 struct Expression *globalsListHead;
69 struct Expression *globalsListTail;
70};
71
72
73struct Epoch {
74 struct Trace *traceListHead;
75 struct Trace *traceListTail;
76} *epoch;
77
78struct WatchInfo {
79 struct WatchInfo *next;
80 struct WatchInfo *prev;
81 int hitNumber;
82 const char *value;
83};
84
85
86static void cb_console(const char *str, void *data)
87{
88 printf("CONSOLE> %s\n", str);
89}
90
91
92/* Note that unlike what's documented in gdb docs it isn't usable. */
93static void cb_target(const char *str, void *data)
94{
95 printf("TARGET> %s\n", str);
96}
97
98
99static void cb_log(const char *str, void *data)
100{
101 printf("LOG> %s\n", str);
102}
103
104
105static void cb_to(const char *str, void *data)
106{
107 printf(">> %s", str);
108}
109
110
111static void cb_from(const char *str, void *data)
112{
113 printf("<< %s\n", str);
114}
115
116
117static void cb_async(mi_output * o, void *data)
118{
119 printf("ASYNC\n");
120 async_c++;
121}
122
123static int isInCodeBase(const char *name)
124{
125 struct FileName *fileName = fileNameListHead;
126 while (fileName) {
127 if (strstr(name, fileName->name))
128 return MONKEY_YES;
129 fileName = fileName->next;
130 }
131 return MONKEY_NO;
132}
133
134
135static int wait_for_stop(struct MONKEY_ACTION_Context *cntxt)
136{
137 static int safetyCount = 0;
138
139 while (!mi_get_response(cntxt->gdb_handle))
140 usleep(GDB_MI_ASYNC_WAIT);
141 /* The end of the async. */
142
143 cntxt->gdb_stop_reason = mi_res_stop(cntxt->gdb_handle);
144
145 if (cntxt->gdb_stop_reason) {
146 safetyCount = 0; // reset the Safety Count whenever you stop for a meaningful reason
147
148 switch (cntxt->gdb_stop_reason->reason) {
149 case sr_exited_normally:
150 return GDB_STATE_EXIT_NORMALLY;
151 case sr_signal_received:
152 //gmi_set_unwind_on_signal_on(cntxt->gdb_handle); // Program crashed. From now on preserve stack on any further received signals
153 break;
154 case sr_bkpt_hit:
155 {
156 /* continue execution */
157 gmi_exec_continue(cntxt->gdb_handle);
158 return wait_for_stop(cntxt);
159 }
160 case sr_wp_trigger:
161 {
162 /* Execution stopped because of hitting a watch point */
163 static int watchPointHitNumber = 0;
164 struct WatchInfo *watchInfo =
165 MONKEY_malloc(sizeof(struct WatchInfo));
166 watchInfo->hitNumber = ++watchPointHitNumber;
167 watchInfo->value = cntxt->gdb_stop_reason->wp_val;
168 MONKEY_CONTAINER_DLL_insert(watchInfoListHead,
169 watchInfoListTail, watchInfo);
170 if (watchPointHitNumber == 1023)
171 printf("HEY! 1023! WE ARE GETTING OUT OF THE LOOP!\n");
172 gmi_exec_continue(cntxt->gdb_handle);
173 return wait_for_stop(cntxt);
174 }
175 case sr_wp_scope:
176 gmi_exec_continue(cntxt->gdb_handle);
177 return wait_for_stop(cntxt);
178 default:
179 break;
180 }
181
182 /* Reaching this line means that the program has stopped abnormally
183 * OR we are in backtracking mode, and it's a step backward */
184 cntxt->gdb_frames = gmi_stack_list_frames(cntxt->gdb_handle);
185 while(cntxt->gdb_frames && !cntxt->gdb_frames->file) {
186 cntxt->gdb_frames = cntxt->gdb_frames->next;
187 }
188
189 if(cntxt->gdb_frames && !isInCodeBase(cntxt->gdb_frames->file)) {
190 struct FileName* filen;
191 for(filen=fileNameListHead; filen; filen = filen->next)
192 if(filen->name) printf("%s\n", filen->name);
193 while(cntxt->gdb_frames) {
194 if(cntxt->gdb_frames->file)
195 printf("file: %s\nisInCodeBase: %d\n", cntxt->gdb_frames->file, isInCodeBase(cntxt->gdb_frames->file));
196 if(cntxt->gdb_frames->file && isInCodeBase(cntxt->gdb_frames->file)) {
197 break;
198 }
199 cntxt->gdb_frames = cntxt->gdb_frames->next;
200 }
201
202 if (cntxt->gdb_frames && cntxt->run_reverse) {
203 /* We are in backtracking mode, we need to move GDB from the shared library to our source code */
204 stoppedInSharedLib = MONKEY_YES;
205 gmi_break_insert(cntxt->gdb_handle, cntxt->gdb_frames->file,
206 cntxt->gdb_frames->line);
207 gmi_exec_continue_reverse(cntxt->gdb_handle);
208 while (!mi_get_response(cntxt->gdb_handle))
209 usleep(GDB_MI_ASYNC_WAIT);
210 cntxt->gdb_frames = gmi_stack_list_frames(cntxt->gdb_handle);
211 }
212 }
213
214 if (NULL == cntxt->gdb_frames) {
215 fprintf(stderr, "Cannot get stack frames from gdb. You might be debugging the wrong program.\n"); // Something really bad happened. Abort!
216 return GDB_STATE_ERROR;
217 }
218
219 /* Change current GDB frame to the one containing source code */
220 gmi_stack_select_frame(cntxt->gdb_handle,
221 cntxt->gdb_frames->level);
222
223 return GDB_STATE_STOPPED;
224 }
225 else if ((MONKEY_YES == cntxt->run_reverse) && (safetyCount < GDB_SAFETY_COUNT)) { // GDB_SAFETY_COUNT prevents infinite analysis
226 /* If the stop reason is NULL, don't bail out immediately, wait for stop again.
227 * It happens when a breakpoint is placed (for backtracking) that the program stops for an unknown reason,
228 * resulting in a NULL stop reason which causes Monkey to bail out before finishing its analysis. This else if
229 * clause prevents premature bail out
230 */
231 safetyCount++;
232 return wait_for_stop(cntxt);
233 }
234
235 return GDB_STATE_ERROR;
236}
237
238
239int
240MONKEY_ACTION_report_file(struct MONKEY_ACTION_Context *cntxt,
241 const char *dumpFileName, int isXML)
242{
243 FILE *f;
244 f = MONKEY_XML_WRITER_create_document(dumpFileName);
245 if (NULL == f) {
246 fprintf(stderr, "Error: pathologist was not able to create report file.\n");
247 return MONKEY_NO;
248 }
249 MONKEY_XML_WRITER_write_document(f, cntxt->xml_report_node);
250 if (0 != fclose(f)) {
251 fprintf(stderr, "Error: pathologist could not close report file.\n");
252 return MONKEY_NO;
253 }
254 return MONKEY_OK;
255}
256
257
258int MONKEY_ACTION_report_email(struct MONKEY_ACTION_Context *cntxt, const char * dumpFileName)
259{
260 FILE *f;
261 MONKEY_ACTION_format_report_xml(cntxt);
262 f = MONKEY_XML_WRITER_create_document(dumpFileName);
263 MONKEY_XML_WRITER_write_document(f, cntxt->xml_report_node);
264 fclose(f);
265 sendMail(NULL, dumpFileName, cntxt->email_address);
266 return MONKEY_OK;
267}
268
269
270static int
271iterateFileNames(void *cls, int numColumns, char **colValues,
272 char **colNames)
273{
274 struct FileName *fileName;
275 char *token;
276
277 if (NULL == colValues[0])
278 return 1; /* Error */
279
280 // This is done to extract the only the file name from the full path coming from the Database
281 token = strrchr(colValues[0], '/');
282 if (NULL == token) {
283 token = colValues[0];
284 } else {
285 token++;
286 }
287 fileName = MONKEY_malloc(sizeof(struct FileName));
288 fileName->prev = NULL;
289 fileName->next = NULL;
290 fileName->name = MONKEY_strdup(token);
291 MONKEY_CONTAINER_DLL_insert(fileNameListHead, fileNameListTail, fileName);
292 return 0; /* OK */
293}
294
295
296static int
297outerScopesCallback(void *cls, int numColumns, char **colValues,
298 char **colNames)
299{
300 if (NULL == colValues[0])
301 return 1; /* Error */
302
303 struct ScopeEnd *scopeEnd = MONKEY_malloc(sizeof(struct ScopeEnd));
304 scopeEnd->lineNo = atoi(colValues[0]);
305 MONKEY_CONTAINER_DLL_insert(scopeEndListHead, scopeEndListTail,
306 scopeEnd);
307 return 0; /* OK */
308}
309
310
311static int
312iterateExpressions(void *cls, int numColumns, char **colValues,
313 char **colNames)
314{
315 struct Expression *expression;
316 struct Function *function = (struct Function *) cls;
317
318 if (NULL == colValues[0] || NULL == colValues[1])
319 return 1; /* Error */
320
321 expression = MONKEY_malloc(sizeof(struct Expression));
322 expression->expressionSyntax = MONKEY_strdup(colValues[0]);
323 expression->isCall = atoi(colValues[1]);
324 expression->expressionValue = NULL;
325 expression->next = NULL;
326 expression->prev = NULL;
327
328 MONKEY_CONTAINER_DLL_insert(function->expressionListHead,
329 function->expressionListTail, expression);
330
331 return 0; /* OK */
332}
333
334
335static int
336iterateGlobals(void *cls, int numColumns, char **colValues,
337 char **colNames)
338{
339 struct Expression *expression;
340 struct Trace *trace = (struct Trace *) cls;
341
342 if (NULL == colValues[0] || NULL == colValues[1])
343 return 1; /* Error */
344
345 expression = MONKEY_malloc(sizeof(struct Expression));
346 expression->expressionSyntax = MONKEY_strdup(colValues[0]);
347 expression->isCall = atoi(colValues[1]);
348 expression->expressionValue = NULL;
349 expression->next = NULL;
350 expression->prev = NULL;
351
352 MONKEY_CONTAINER_DLL_insert(trace->globalsListHead,
353 trace->globalsListTail, expression);
354
355 return 0; /* OK */
356}
357
358
359static int
360scopeEndCallback(void *cls, int numColumns, char **colValues,
361 char **colNames)
362{
363 int *scopeEnd = (int *) cls;
364
365 *scopeEnd = atoi(colValues[0]);
366 if (*scopeEnd < 0)
367 return 1; /* Error */
368 return 0;
369}
370
371
372static int isAssignment(const char *expressionSyntax)
373{
374 return (NULL != strstr(expressionSyntax, "=")) ? MONKEY_YES : MONKEY_NO;
375}
376
377
378static struct Expression*
379analyzeExpressionValue( struct MONKEY_ACTION_Context *cntxt,
380 struct Expression *expr,
381 struct Expression **expressionListHead,
382 struct Expression **expressionListTail)
383{
384 MONKEY_assert(expr);
385 struct Expression *next = expr->next;
386 struct Expression *removedExpression = expr;
387
388 // We will not evaluate function calls (because GDB will evaluate by calling the function)
389 if( expr->isCall )
390 goto remove;
391
392 // We should NOT evaluate assignments, otherwise subsequent expression evaluations will be spoiled
393 else if( isAssignment(expr->expressionSyntax) )
394 goto remove;
395
396 // NULL Pointer are also ignored (cause theire NULL)
397 if (strcmp(expr->expressionSyntax, "NULL") == 0 ||
398 strcmp(expr->expressionSyntax, "0x0") == 0 ||
399 strcmp(expr->expressionSyntax, "((void*)0)") == 0)
400 goto remove;
401
402 expr->expressionValue =
403 gmi_data_evaluate_expression( cntxt->gdb_handle,
404 expr->expressionSyntax);
405
406 // ignore trivial report entries (constants for that matter)
407 if (expr->expressionValue && strcmp(expr->expressionSyntax, expr->expressionValue) == 0)
408 goto remove;
409
410 // ignore functionpointers with their default names
411 size_t value_len; //= strlen(expr->expressionValue);
412 size_t syntax_len; //= strlen(expr->expressionSyntax);
413 if (expr->expressionValue &&
414 (value_len = strlen(expr->expressionValue)) > (syntax_len = strlen(expr->expressionSyntax)) + 2 &&
415 !strncmp(expr->expressionValue + value_len - 1, ">", 1) &&
416 !strncmp(expr->expressionValue + value_len - syntax_len - 2, "<", 1) &&
417 !strncmp(expr->expressionValue + value_len - syntax_len - 1, expr->expressionSyntax, syntax_len))
418 goto remove;
419
420 if (NULL != expr->expressionValue
421 && (strcmp(expr->expressionValue, "0x0") == 0
422 || strcmp(expr->expressionValue, "NULL") == 0))
423 {
424 expr->expressionValue = "NULL";
425 cntxt->gdb_null_variable = expr->expressionSyntax;
426 cntxt->has_null = MONKEY_YES;
427 }
428
429 return next;
430
431remove:
432 MONKEY_CONTAINER_DLL_remove(*expressionListHead,
433 *expressionListTail,
434 removedExpression);
435 return next;
436}
437
438
439static int
440analyzeExpressionValues(struct Function *function,
441 struct MONKEY_ACTION_Context *cntxt)
442{
443 struct Expression *tmp;
444
445 tmp = function->expressionListHead;
446 while (NULL != tmp) {
447 tmp = analyzeExpressionValue(cntxt, tmp, &(function->expressionListHead), &(function->expressionListTail));
448 }
449
450 return MONKEY_OK;
451}
452
453
454static int
455analyzeGlobalsValues(struct Trace *trace,
456 struct MONKEY_ACTION_Context *cntxt)
457{
458 struct Expression *tmp;
459
460 tmp = trace->globalsListHead;
461 while (NULL != tmp) {
462 tmp = analyzeExpressionValue(cntxt, tmp, &(trace->globalsListHead), &(trace->globalsListTail));
463 }
464
465 return MONKEY_OK;
466}
467
468
469static int flushTrace(struct Trace *trace)
470{
471 struct Function *functionPtr = NULL;
472 struct Expression *expressionPtr = NULL;
473
474 while (NULL != trace->functionListHead) {
475 functionPtr = trace->functionListHead;
476 trace->functionListHead = trace->functionListHead->next;
477
478 while (NULL != functionPtr->expressionListHead) {
479 expressionPtr = functionPtr->expressionListHead;
480 functionPtr->expressionListHead =
481 functionPtr->expressionListHead->next;
482
483 MONKEY_free((char *) expressionPtr->expressionSyntax);
484 MONKEY_free(expressionPtr);
485 }
486 MONKEY_free(functionPtr);
487 }
488 return MONKEY_OK;
489}
490
491static void printTrace()
492{
493 int i = 0;
494 struct Function *functionPtr;
495 struct Expression *expressionPtr;
496 struct Trace *tracePtr = epoch->traceListHead;
497 while (NULL != tracePtr) {
498 printf("Program Stack Trace: Epoch Step %d\n", i++);
499 functionPtr = tracePtr->functionListHead;
500 while (NULL != functionPtr) {
501 printf("Function: %s, file: %s, line: %d\n", functionPtr->name,
502 functionPtr->file, functionPtr->line);
503 printf
504 ("--------------------------------------------------------------------------------------------------\n");
505 printf("Expressions:\n");
506
507 expressionPtr = functionPtr->expressionListHead;
508 while (NULL != expressionPtr) {
509 printf("%s = %s\n",
510 expressionPtr->expressionSyntax,
511 (NULL ==
512 expressionPtr->
513 expressionValue) ? "No Value" : expressionPtr->
514 expressionValue);
515 expressionPtr = expressionPtr->next;
516 }
517
518 functionPtr = functionPtr->next;
519 }
520 printf
521 ("############################## End Stack Trace ######################################################\n\n");
522 tracePtr = tracePtr->next;
523 }
524}
525
526static void flushScopeEndList()
527{
528 struct ScopeEnd* scopeEndPtr;
529 while (NULL != scopeEndListHead) {
530 scopeEndPtr = scopeEndListHead;
531 scopeEndListHead = scopeEndPtr->next;
532 MONKEY_free(scopeEndPtr);
533 }
534
535 scopeEndListHead = NULL;
536 scopeEndListTail = NULL;
537}
538
539int MONKEY_ACTION_inspect_expression_database(struct MONKEY_ACTION_Context *cntxt)
540{
541 int ret = MONKEY_OK;
542 int stackDepth = 0;
543 char* file_names = NULL;
544 struct Function *function = NULL;
545 struct Trace *trace = NULL;
546
547 /* Variables used across recursive calls */
548 static struct MONKEY_EDB_Context *edbCntxt;
549
550 if (NULL == epoch) {
551 epoch = MONKEY_malloc(sizeof(struct Epoch));
552 epoch->traceListHead = NULL;
553 epoch->traceListTail = NULL;
554 }
555
556 // Initialize the trace structure for this particular epoch step
557 trace = MONKEY_malloc(sizeof(struct Trace));
558 trace->globalsListHead = NULL;
559 trace->globalsListTail = NULL;
560 MONKEY_CONTAINER_DLL_insert_tail(epoch->traceListHead,
561 epoch->traceListTail, trace);
562
563
564 // Create a connection to the Expression Database
565 edbCntxt = MONKEY_EDB_connect(cntxt->expression_database_path);
566 if (NULL == edbCntxt) {
567 fprintf(stderr, "Unable to connect to Expression Database file!\n");
568 ret = MONKEY_NO;
569 goto cleanup;
570 }
571
572 while( cntxt->gdb_frames && stackDepth <= cntxt->scope_depth) {
573 gmi_stack_select_frame(cntxt->gdb_handle, cntxt->gdb_frames->level);
574 gmi_stack_info_frame(cntxt->gdb_handle);
575
576 // build the function struct
577 function = MONKEY_malloc(sizeof(struct Function));
578 function->depth = stackDepth++;
579 function->line = cntxt->gdb_frames->line;
580 function->name = cntxt->gdb_frames->func;
581 function->file = cntxt->gdb_frames->file;
582 function->expressionListHead = NULL;
583 function->expressionListTail = NULL;
584 function->next = NULL;
585 function->prev = NULL;
586 MONKEY_CONTAINER_DLL_insert_tail(trace->functionListHead,
587 trace->functionListTail, function);
588
589 // Retrieve scope expressions from the database
590 MONKEY_EDB_get_expressions(edbCntxt,
591 cntxt->gdb_frames->file,
592 cntxt->gdb_frames->line,
593 &iterateExpressions, function);
594
595 // Do value analysis for relevant expressions
596 analyzeExpressionValues(function, cntxt);
597
598 // add current filename to the list
599 char* tmp = file_names;
600 MONKEY_asprintf(&file_names,
601 "%s OR file_name LIKE \'%%%s\'",
602 file_names,
603 cntxt->gdb_frames->file);
604 MONKEY_free_non_null(tmp);
605
606 /* Now, dive deeper into the stack trace */
607 cntxt->gdb_frames = cntxt->gdb_frames->next;
608 }
609
610
611 // Retrieve globals from the database
612 file_names += 10; // cut the first 10 chars "(null) OR "
613 MONKEY_EDB_get_globals( edbCntxt,
614 file_names,
615 &iterateGlobals, trace);
616 file_names -= 10;
617
618 // Do value analysis for globals
619 analyzeGlobalsValues(trace, cntxt);
620
621cleanup:
622 MONKEY_EDB_disconnect(edbCntxt);
623 MONKEY_free_non_null(file_names);
624 return ret;
625}
626
627
628int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context
629 *cntxt)
630{
631 const char *failureFile = epoch->traceListHead->functionListHead->file;
632 const char *failureFunction =
633 epoch->traceListHead->functionListHead->name;
634 struct Trace *tracePtr = epoch->traceListHead;
635 int oldLine;
636
637 /*
638 * We execute one step back operation before starting analysis. We do that to go to the expression before the one where the crash occurred.
639 * Because we already have the expression where the crash happened in our stack structure from the previous epoch step (the initial epoch)
640 */
641 if (MONKEY_NO == stoppedInSharedLib) {
642 if (MONKEY_NO != gmi_exec_next_reverse(cntxt->gdb_handle)) {
643 while (!mi_get_response(cntxt->gdb_handle))
644 usleep(GDB_MI_ASYNC_WAIT);
645 } else {
646 fprintf(stderr, "Error: Reverse Execution has failed! Backtracking might not be supported for the current architecture.\n");
647 if (MONKEY_YES == cntxt->gdb_connected) {
648 mi_disconnect(cntxt->gdb_handle); // No need for gdb mi at this point!
649 cntxt->gdb_connected = MONKEY_NO;
650 }
651 return MONKEY_NO;
652 }
653 }
654
655 /* Do reverse execution for all expressions in the function in which the failure occurred */
656 do {
657 oldLine = tracePtr->functionListHead->line;
658 if (MONKEY_NO != gmi_exec_next_reverse(cntxt->gdb_handle)) {
659 if (GDB_STATE_ERROR == wait_for_stop(cntxt)) {
660 fprintf(stderr, "Error: Analysis during Reverse Execution has failed!\n");
661 return MONKEY_NO;
662 }
663 if (oldLine == cntxt->gdb_frames->line)
664 break;// We reached the end of record history TODO: DIRTY SOLUTION! WILL FAIL IF TWO EXPRESSIONS ON THE SAME LINE
665 MONKEY_ACTION_inspect_expression_database(cntxt);
666 } else {
667 fprintf(stderr, "Error: Reverse Execution has failed!\n");
668 return MONKEY_NO;
669 }
670
671 tracePtr = tracePtr->next; // tracePtr will have the new trace added after examining the expression database for this reverse execution step
672 } while ((NULL != tracePtr)
673 && (strcmp(failureFile, tracePtr->functionListHead->file) ==
674 0)
675 && (strcmp(failureFunction, tracePtr->functionListHead->name)
676 == 0));
677
678 // stop recording and return
679 gmi_exec_record_stop(cntxt->gdb_handle);
680 return MONKEY_OK;
681}
682
683int MONKEY_ACTION_rerun_with_valgrind(struct MONKEY_ACTION_Context
684 *cntxt)
685{
686 char *valgrindCommand;
687 FILE *valgrindPipe;
688 const char *valgrindPath = cntxt->valgrind_binary_path;
689 struct stat buf;
690
691 if (NULL == valgrindPath)
692 valgrindPath = "/usr/bin/valgrind"; /* Assumption for valgrind installation */
693
694 /* Check if Valgrind is installed */
695 if (stat(valgrindPath, &buf) != 0 && errno == ENOENT ) {
696 fprintf(stderr,
697 "Warning: Valgrind is not installed. Memory check aborted!\n");
698 return MONKEY_NO;
699 }
700
701 MONKEY_asprintf(&cntxt->valgrind_output_tmp_file_name, "%d", rand());
702 cntxt->debug_mode = DEBUG_MODE_VALGRIND;
703 MONKEY_asprintf(&valgrindCommand,
704 "%s --leak-check=yes --log-file=%s %s", valgrindPath,
705 cntxt->valgrind_output_tmp_file_name,
706 cntxt->binary_name);
707 valgrindPipe = popen(valgrindCommand, "r");
708 if (NULL == valgrindPipe) {
709 fprintf(stderr, "Error in running Valgrind! Memory check aborted!\n");
710 MONKEY_free(valgrindCommand);
711 return MONKEY_NO;
712 }
713
714 pclose(valgrindPipe);
715 MONKEY_free(valgrindCommand);
716 return MONKEY_OK;
717}
718
719
720int MONKEY_ACTION_rerun_with_gdb(struct MONKEY_ACTION_Context
721 *cntxt)
722{
723 struct MONKEY_EDB_Context *edbCntxt;
724 struct stat buf;
725
726 /* Check if gdb is installed */
727 if (NULL == cntxt->gdb_binary_path) {
728 cntxt->gdb_binary_path = "/usr/bin/gdb"; /* Assumption for gdb default installation */
729 }
730 if (stat(cntxt->gdb_binary_path, &buf) != 0 && errno == ENOENT ) {
731 fprintf(stderr,
732 "Error: gdb is not installed!\n");
733 return MONKEY_NO;
734 }
735
736 epoch = NULL; /* Initializing epoch Data Structure */
737 cntxt->debug_mode = DEBUG_MODE_GDB;
738 /* This is like a file-handle for fopen.
739 Here we have all the state of gdb "connection". */
740 if (NULL != cntxt->gdb_binary_path)
741 mi_set_gdb_exe(cntxt->gdb_binary_path);
742 int ret;
743
744 /* Connect to gdb child. */
745 cntxt->gdb_handle = mi_connect_local();
746 if (!cntxt->gdb_handle) {
747 fprintf(stderr, "Error: failed to connect to gdb!\n");
748 return MONKEY_NO;
749 }
750 fprintf(stderr, "Info: Connected to gdb!\n");
751 cntxt->gdb_connected = MONKEY_YES;
752
753 /* Set all callbacks. */
754 mi_set_console_cb(cntxt->gdb_handle, cb_console, NULL);
755 mi_set_target_cb(cntxt->gdb_handle, cb_target, NULL);
756 mi_set_log_cb(cntxt->gdb_handle, cb_log, NULL);
757 mi_set_async_cb(cntxt->gdb_handle, cb_async, NULL);
758 mi_set_to_gdb_cb(cntxt->gdb_handle, cb_to, NULL);
759 mi_set_from_gdb_cb(cntxt->gdb_handle, cb_from, NULL);
760
761 /* Set the name of the child and the command line arguments. */
762 if (!gmi_set_exec(cntxt->gdb_handle, cntxt->binary_name, cntxt->binaryArgs)) {
763 fprintf(stderr, "Error: could not set gdb exec y args\n");
764 goto fail;
765 }
766
767 /* Tell gdb to attach the child to a terminal. */
768 if (!gmi_target_terminal(cntxt->gdb_handle, ttyname(STDIN_FILENO))) {
769 fprintf(stderr, "Error: could not select gdb target terminal\n");
770 goto fail;
771 }
772
773
774 if (MONKEY_YES == cntxt->run_reverse) {
775 /* If Backtracking is enabled, we must set a breakpoint at the main function, starting the program, then starting recording */
776 mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0, NULL, -1, -1, "main");
777 if (NULL == bp) {
778 fprintf(stderr, "Error: gdb could not set a breakpoint at function:%s\n",
779 cntxt->inspect_function);
780 goto fail;
781 }
782 mi_free_bkpt(bp);
783 }
784
785
786 if ((NULL != cntxt->inspect_expression) && (NULL != cntxt->inspect_function)) {
787 /* Setting a breakpoint at the function containing the expression to inspect */
788 mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0, NULL, -1, -1, cntxt->inspect_function);
789 if (NULL == bp) {
790 fprintf(stderr, "Error: gdb could not set a breakpoint at function:%s\n", cntxt->inspect_function);
791 goto fail;
792 }
793 mi_free_bkpt(bp);
794 }
795
796 /* Prepare a list of the file names for the source files we are analyzing */
797 edbCntxt = MONKEY_EDB_connect(cntxt->expression_database_path);
798 if (NULL == edbCntxt) {
799 fprintf(stderr,
800 "Unable to connect to Expression Database file!\n");
801 goto fail;
802 }
803
804 if (MONKEY_OK != MONKEY_EDB_get_file_names(edbCntxt, &iterateFileNames, NULL)) {
805 fprintf(stderr, "Error: Pathologist could not retrieve source file names from expression database!\n");
806 goto fail;
807 }
808 MONKEY_EDB_disconnect(edbCntxt);
809
810
811 /* Run the program. */
812 if (!gmi_exec_run(cntxt->gdb_handle)) {
813 fprintf(stderr, "Error: gdb could not run the target program!\n");
814 goto fail;
815 }
816
817 /* Backtracking is issued after running the program */
818 if (MONKEY_YES == cntxt->run_reverse) {
819 gmi_exec_record_process(cntxt->gdb_handle);
820 }
821
822 /* Here we should be stopped when the program crashes */
823 ret = wait_for_stop(cntxt);
824 if (ret == GDB_STATE_ERROR || ret == GDB_STATE_EXIT_NORMALLY) {
825 if (MONKEY_YES == cntxt->gdb_connected) {
826 mi_disconnect(cntxt->gdb_handle);
827 cntxt->gdb_connected = MONKEY_NO;
828 }
829 }
830
831 return ret;
832
833 // cleanup and abort
834fail:
835 if (MONKEY_YES == cntxt->gdb_connected) {
836 mi_disconnect(cntxt->gdb_handle);
837 cntxt->gdb_connected = MONKEY_NO;
838 }
839 return MONKEY_NO;
840}
841
842
843static const char *expressionListToString(struct Expression *head)
844{
845 char *string = MONKEY_strdup("");
846 char *strTmp;
847 struct Expression *tmp;
848
849 for (tmp = head; NULL != tmp; tmp = tmp->next) {
850 MONKEY_asprintf(&strTmp,
851 "%s%s => %s\n",
852 string,
853 tmp->expressionSyntax,
854 NULL ==
855 tmp->
856 expressionValue ? "Not evaluated" :
857 tmp->expressionValue);
858 MONKEY_free(string);
859 string = strTmp;
860 }
861 return string;
862}
863
864#if 0
865static int getWatchInfoListSize(struct WatchInfo *head)
866{
867 int count = 0;
868 int largestStr = 0;
869 struct WatchInfo *tmp = head;
870
871 while (NULL != tmp) {
872 if (largestStr < strlen(tmp->value))
873 largestStr = strlen(tmp->value);
874 tmp = tmp->next;
875 count++;
876 }
877
878 return count * largestStr;
879}
880
881static const char *watchInfoListToString(struct WatchInfo *head)
882{
883 char *string = MONKEY_malloc(getWatchInfoListSize(head));
884 char *strTmp;
885 struct WatchInfo *tmp = head;
886
887 MONKEY_asprintf(&strTmp, "%s\t \t%s\n", tmp->hitNumber, tmp->value);
888 strcpy(string, strTmp);
889 MONKEY_free(strTmp);
890 tmp = tmp->next;
891
892 while (NULL != tmp) {
893 MONKEY_asprintf(&strTmp, "%s\t \t%s\n", tmp->hitNumber,
894 tmp->value);
895 strcat(string, strTmp);
896 MONKEY_free(strTmp);
897 tmp = tmp->next;
898 }
899
900 return string;
901}
902#endif
903
904static const char *getValgrindOutput(struct MONKEY_ACTION_Context *cntxt)
905{
906 char *valgrindOutput;
907 int size;
908 FILE *valgrindFile = fopen(cntxt->valgrind_output_tmp_file_name, "r");
909 fseek(valgrindFile, 0L, SEEK_END);
910 size = ftell(valgrindFile);
911 fseek(valgrindFile, 0L, SEEK_SET);
912
913 valgrindOutput = MONKEY_malloc(size);
914 fread(valgrindOutput, size - 1, 1, valgrindFile);
915 fclose(valgrindFile);
916 return valgrindOutput;
917}
918
919
920static struct MONKEY_XML_Node *createXmlSimpleNode(const char *nodeName,
921 const char
922 *nodeInnerText)
923{
924 struct MONKEY_XML_Node *node =
925 MONKEY_XML_WRITER_new_node(nodeName, nodeInnerText);
926 return node;
927}
928
929
930static struct MONKEY_XML_Node *createXmlCrashNode(const char *category,
931 const char *function,
932 int line,
933 const char *file)
934{
935 struct MONKEY_XML_Node *node;
936 char *lineStr;
937
938 MONKEY_asprintf(&lineStr, "%d", line);
939 node = MONKEY_XML_WRITER_new_node("crash", NULL);
940 MONKEY_XML_WRITER_add_attribute(node, "category", category);
941 MONKEY_XML_WRITER_add_attribute(node, "function", function);
942 MONKEY_XML_WRITER_add_attribute(node, "line", lineStr);
943 MONKEY_XML_WRITER_add_attribute(node, "file", file);
944 return node;
945}
946
947
948static struct MONKEY_XML_Node *createXmlEpochStep(int step)
949{
950 struct MONKEY_XML_Node *node;
951 char *stepStr;
952 MONKEY_asprintf(&stepStr, "%d", step);
953 node = MONKEY_XML_WRITER_new_node("epoch", NULL);
954 MONKEY_XML_WRITER_add_attribute(node, "step", stepStr);
955 return node;
956}
957
958
959static struct MONKEY_XML_Node *createXmlFunctionNode(const char *name,
960 int line,
961 const char *file,
962 int depth)
963{
964 struct MONKEY_XML_Node *node;
965 char *lineStr;
966 char *depthStr;
967
968 MONKEY_asprintf(&lineStr, "%d", line);
969 MONKEY_asprintf(&depthStr, "%d", depth);
970 node = MONKEY_XML_WRITER_new_node("function", NULL);
971 MONKEY_XML_WRITER_add_attribute(node, "name", name);
972 MONKEY_XML_WRITER_add_attribute(node, "line", lineStr);
973 MONKEY_XML_WRITER_add_attribute(node, "file", file);
974 MONKEY_XML_WRITER_add_attribute(node, "depth", depthStr);
975 return node;
976}
977
978
979static struct MONKEY_XML_Node *createXmlExpressionNode(const char *name,
980 const char *value)
981{
982 struct MONKEY_XML_Node *node;
983
984 node = MONKEY_XML_WRITER_new_node("expression", value);
985 MONKEY_XML_WRITER_add_attribute(node, "name", name);
986 return node;
987}
988
989
990static struct MONKEY_XML_Node *createXmlGlobalExpressionNode(const char *name,
991 const char *value)
992{
993 struct MONKEY_XML_Node *node;
994
995 node = MONKEY_XML_WRITER_new_node("expression", value);
996 MONKEY_XML_WRITER_add_attribute(node, "name", name);
997 return node;
998}
999
1000
1001int MONKEY_ACTION_is_Nullpointer(struct MONKEY_ACTION_Context* cntxt)
1002{
1003 mi_asm_insns* disassembled_code = gmi_data_disassemble_se(cntxt->gdb_handle, "$pc", "$pc+1", 0);
1004 char* reg;
1005 while(reg = strstr(disassembled_code->ins->inst, "(%")) {
1006 //printf("%s\n", reg);
1007 reg++;
1008 size_t len = strcspn(reg, "),");
1009 reg[0]='$';
1010 reg[len]='\0';
1011 char* val = gmi_data_evaluate_expression(cntxt->gdb_handle, reg);
1012 //printf("%s\n", val);
1013 if( !strcmp(val, "0") ) return 1;
1014 }
1015 return 0;
1016}
1017
1018
1019int MONKEY_ACTION_format_report_xml(struct MONKEY_ACTION_Context
1020 *cntxt)
1021{
1022 int i = 0;
1023 struct MONKEY_XML_Node *node;
1024 struct MONKEY_XML_Node *historyNode;
1025 struct MONKEY_XML_Node *traceNode;
1026 struct MONKEY_XML_Node *globalsNode;
1027 struct Trace *tracePtr = epoch->traceListHead;
1028 struct Function *functionPtr = tracePtr->functionListHead;
1029 struct Expression *expressionPtr;
1030
1031
1032 switch (cntxt->bug_detected) {
1033 case BUG_NULL_POINTER:
1034 cntxt->xml_report_node = createXmlCrashNode("npe", functionPtr->name, functionPtr->line, functionPtr->file);
1035 break;
1036 case BUG_BAD_MEM_ACCESS:
1037 cntxt->xml_report_node = createXmlCrashNode("Bad memory access", functionPtr->name, functionPtr->line, functionPtr->file);
1038 node = MONKEY_XML_WRITER_add_child(cntxt->xml_report_node, createXmlSimpleNode("valgrind", getValgrindOutput(cntxt)));
1039 break;
1040 case BUG_ABORT:
1041 cntxt->xml_report_node = createXmlCrashNode("Assertion Failure", functionPtr->name, functionPtr->line, functionPtr->file);
1042 break;
1043 case BUG_ARITHMETIC:
1044 cntxt->xml_report_node = createXmlCrashNode("Division By Zero", functionPtr->name, functionPtr->line, functionPtr->file);
1045 break;
1046 case BUG_SIG_BUS:
1047 cntxt->xml_report_node = createXmlCrashNode("Bus Error", functionPtr->name, functionPtr->line, functionPtr->file);
1048 break;
1049 default:
1050 cntxt->xml_report_node = createXmlCrashNode("Unknown", functionPtr->name, functionPtr->line, functionPtr->file);
1051 break;
1052 }
1053
1054 historyNode = MONKEY_XML_WRITER_add_child(cntxt->xml_report_node, createXmlSimpleNode("history", NULL));
1055
1056 /* Adding Stack Trace Nodes to XML Report */
1057 while (NULL != tracePtr) {
1058 node = MONKEY_XML_WRITER_add_child(historyNode, createXmlEpochStep(i));
1059 traceNode = MONKEY_XML_WRITER_add_child(node, createXmlSimpleNode("trace", NULL));
1060 globalsNode = MONKEY_XML_WRITER_add_child(node, createXmlSimpleNode("globals", NULL));
1061
1062 functionPtr = tracePtr->functionListHead;
1063 while (NULL != functionPtr) {
1064 node = MONKEY_XML_WRITER_add_child(traceNode, createXmlFunctionNode(functionPtr->name,
1065 functionPtr->line,
1066 functionPtr->file,
1067 functionPtr->depth));
1068 node = MONKEY_XML_WRITER_add_child(node, createXmlSimpleNode("expressions", NULL));
1069
1070 expressionPtr = functionPtr->expressionListHead;
1071 while (NULL != expressionPtr) {
1072 // ignore non helpful expressions
1073 if( expressionPtr->expressionValue )
1074 MONKEY_XML_WRITER_add_child(node, createXmlExpressionNode(expressionPtr->expressionSyntax, expressionPtr->expressionValue));
1075 expressionPtr = expressionPtr->next;
1076 }
1077
1078 functionPtr = functionPtr->next;
1079 }
1080
1081 expressionPtr = tracePtr->globalsListHead;
1082 while( expressionPtr ) {
1083 if( expressionPtr->expressionValue )
1084 MONKEY_XML_WRITER_add_child(globalsNode, createXmlGlobalExpressionNode(expressionPtr->expressionSyntax, expressionPtr->expressionValue));
1085 expressionPtr = expressionPtr->next;
1086 }
1087
1088
1089 tracePtr = tracePtr->next;
1090 i++;
1091 }
1092 return MONKEY_OK;
1093}
1094
1095
1096
1097
1098int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context
1099 *cntxt)
1100{
1101 if (MONKEY_YES == cntxt->gdb_connected) {
1102 mi_disconnect(cntxt->gdb_handle);
1103 cntxt->gdb_connected = MONKEY_NO;
1104 }
1105 if (NULL != cntxt->debug_report)
1106 MONKEY_free(cntxt->debug_report);
1107 if (NULL != cntxt->valgrind_output_tmp_file_name) {
1108 remove(cntxt->valgrind_output_tmp_file_name);
1109 MONKEY_free(cntxt->valgrind_output_tmp_file_name);
1110 }
1111 if (NULL != cntxt->xml_report_node)
1112 MONKEY_XML_WRITER_delete_tree(cntxt->xml_report_node);
1113 if (NULL != cntxt->binaryArgs)
1114 MONKEY_free(cntxt->binaryArgs);
1115
1116 MONKEY_free(cntxt);
1117 return MONKEY_OK;
1118}
1119
1120
1121int MONKEY_ACTION_check_bug_redundancy()
1122{
1123 return MONKEY_OK;
1124}
diff --git a/pathologist/src/pathologist/action.h b/pathologist/src/pathologist/action.h
new file mode 100644
index 0000000..57b748b
--- /dev/null
+++ b/pathologist/src/pathologist/action.h
@@ -0,0 +1,100 @@
1/**
2 * @file monkey/MONKEY_action.h
3 * @brief Monkey API for actions taken by Monkey while debugging
4 */
5
6#ifndef MONKEY_ACTION_H
7#define MONKEY_ACTION_H
8
9#include "gdbmi.h"
10#include "pathologist_xml_writer.h"
11
12#ifdef __cplusplus
13extern "C"
14{
15#if 0 /* keep Emacsens' auto-indent happy */
16}
17#endif
18#endif
19
20
21/* Debug constants */
22#define DEBUG_MODE_GDB 0
23#define GDB_STATE_STOPPED 1
24#define GDB_STATE_EXIT_NORMALLY 2
25#define GDB_STATE_ERROR 3
26#define GDB_SAFETY_COUNT 2
27#define DEBUG_MODE_VALGRIND 4
28#define DEBUG_MODE_REPORT_READY 5
29#define NO_BUG_DETECTED -1
30#define BUG_NULL_POINTER 6
31#define BUG_ABORT 7
32#define BUG_ARITHMETIC 8
33#define BUG_BAD_MEM_ACCESS 9
34#define BUG_SIG_BUS 10
35#define GDB_MI_ASYNC_WAIT 5
36
37/**
38 * Context for the Action API
39 */
40struct MONKEY_ACTION_Context
41{
42 const char *binary_name;
43 char *binaryArgs;
44 const char *email_address;
45 const char *expression_database_path;
46 const char *gdb_binary_path;
47 const char *valgrind_binary_path;
48 const char *inspect_expression;
49 const char *inspect_function;
50 int debug_mode;
51 int bug_detected;
52 int has_null;
53 char *debug_report;
54 struct MONKEY_XML_Node *xml_report_node;
55
56 /* gdb debugging attributes */
57 int run_reverse;
58 int scope_depth;
59 mi_h *gdb_handle;
60 int gdb_connected;
61 const char *gdb_in_use;
62 mi_stop *gdb_stop_reason;
63 mi_frames *gdb_frames;
64 const char *gdb_null_variable;
65
66 /* Valgrind memcheck attributes */
67 char* valgrind_output_tmp_file_name;
68};
69
70
71int MONKEY_ACTION_report_file (struct MONKEY_ACTION_Context
72 *cntxt, const char *dumpFileName, int isXML);
73int MONKEY_ACTION_report_email (struct MONKEY_ACTION_Context
74 *cntxt, const char *dumpFileName);
75int MONKEY_ACTION_inspect_expression_database (struct
76 MONKEY_ACTION_Context
77 *cntxt);
78int MONKEY_ACTION_rerun_with_gdb (struct MONKEY_ACTION_Context
79 *cntxt);
80int MONKEY_ACTION_start_reverse_execution(struct MONKEY_ACTION_Context * cntxt);
81int MONKEY_ACTION_rerun_with_valgrind (struct
82 MONKEY_ACTION_Context
83 *cntxt);
84int MONKEY_ACTION_format_report (struct MONKEY_ACTION_Context
85 *cntxt);
86int
87MONKEY_ACTION_format_report_xml (struct MONKEY_ACTION_Context
88 *cntxt);
89int MONKEY_ACTION_delete_context(struct MONKEY_ACTION_Context *cntxt);
90
91int MONKEY_ACTION_check_bug_redundancy (void);
92
93
94#if 0 /* keep Emacsens' auto-indent happy */
95{
96#endif
97#ifdef __cplusplus
98}
99#endif
100#endif
diff --git a/pathologist/src/pathologist/edb_api.c b/pathologist/src/pathologist/edb_api.c
new file mode 100644
index 0000000..5af26de
--- /dev/null
+++ b/pathologist/src/pathologist/edb_api.c
@@ -0,0 +1,368 @@
1/**
2 * @file monkey/edb_api.c
3 * @brief Monkey API for accessing the Expression Database (edb)
4 */
5
6#include "monkey_common.h"
7#include <stdlib.h>
8#include <stdio.h>
9#include <sqlite3.h>
10#include "pathologist_edb.h"
11
12
13/**
14 * Context for Database connection and Expressions
15 */
16struct MONKEY_EDB_Context
17{
18 /**
19 * Database connection
20 */
21 sqlite3 *db_handle;
22};
23
24
25/**
26 * Establish a connection to the Expression Database
27 *
28 * @param db_file_name path the Expression Database file
29 * @return context to use for Accessing the Expression Database, NULL on error
30 */
31struct MONKEY_EDB_Context *
32MONKEY_EDB_connect (const char *db_file_name)
33{
34 int err;
35 struct MONKEY_EDB_Context *ctxt =
36 MONKEY_malloc (sizeof (struct MONKEY_EDB_Context));
37
38 err = sqlite3_open (db_file_name, &ctxt->db_handle);
39 if (err)
40 {
41 fprintf(stderr,
42 "Cannot open Expression Database. `%s'\n",
43 sqlite3_errmsg (ctxt->db_handle));
44 return NULL;
45 }
46 return ctxt;
47}
48
49
50/**
51 * Disconnect from Database, and cleanup resources
52 *
53 * @param context context containing the Expression Database handle
54 * @return MONKEY_OK on success, MONKEY_NO on failure
55 */
56int
57MONKEY_EDB_disconnect (struct MONKEY_EDB_Context *cntxt)
58{
59 sqlite3_close (cntxt->db_handle);
60 MONKEY_free (cntxt);
61 return MONKEY_OK;
62}
63
64
65
66int
67MONKEY_EDB_get_file_names (struct MONKEY_EDB_Context *cntxt,
68 MONKEY_FileIterator iter,
69 void *iter_cls)
70{
71 int err;
72 char *errMsg;
73 char *query;
74
75 if (MONKEY_asprintf (&query, "select distinct file_name from Expression") == -1)
76 {
77 fprintf(stderr,
78 "Memory allocation problem occurred during creating database query!\n");
79 return MONKEY_NO;
80 }
81
82 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
83 if (err)
84 {
85 fprintf(stderr,
86 "Error occurred while executing Database query. `%s'",
87 errMsg);
88 return MONKEY_NO;
89 }
90 return MONKEY_OK;
91}
92
93
94
95int
96MONKEY_EDB_get_all_outer_scopes(struct MONKEY_EDB_Context
97 *cntxt, const char *file_name,
98 int function_beginning,
99 int scope_in_question_start,
100 int scope_in_question_end,
101 MONKEY_ExpressionIterator
102 iter, void *iter_cls)
103{
104 int err;
105 char *errMsg;
106 char *query;
107
108 if (MONKEY_asprintf
109 (&query,
110 "select distinct end_lineno from Expression where file_name LIKE \'%%%s\' and start_lineno >= %d and start_lineno < %d and end_lineno > %d order by end_lineno",
111 file_name, function_beginning, scope_in_question_start, scope_in_question_end) == -1)
112 {
113 fprintf(stderr,
114 "Memory allocation problem occurred during creating database query!\n");
115 return MONKEY_NO;
116 }
117
118 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
119 if (err)
120 {
121 fprintf(stderr,
122 "Error occurred while executing Database query. `%s'",
123 errMsg);
124 return MONKEY_NO;
125 }
126 return MONKEY_OK;
127}
128
129int
130MONKEY_EDB_expression_function_end_scope(struct MONKEY_EDB_Context
131 *cntxt, const char *file_name,
132 int start_lineno,
133 MONKEY_ExpressionIterator
134 iter, void *iter_cls)
135{
136 int err;
137 char *errMsg;
138 char *query;
139
140 if (MONKEY_asprintf
141 (&query,
142 "select MAX(end_lineno) from Expression where file_name LIKE \'%%%s\' and start_lineno < %d and end_lineno != 32767",
143 file_name, start_lineno) == -1)
144 {
145 fprintf(stderr,
146 "Memory allocation problem occurred during creating database query!\n");
147 return MONKEY_NO;
148 }
149
150 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
151 if (err)
152 {
153 fprintf(stderr,
154 "Error occurred while executing Database query. `%s'",
155 errMsg);
156 return MONKEY_NO;
157 }
158 return MONKEY_OK;
159}
160
161int
162MONKEY_EDB_function_start_line_for_scope(struct MONKEY_EDB_Context
163 *cntxt, const char *file_name,
164 int scope_end,
165 MONKEY_ExpressionIterator
166 iter, void *iter_cls)
167{
168 int err;
169 char *errMsg;
170 char *query;
171
172 if (MONKEY_asprintf
173 (&query,
174 "select MIN(start_lineno) from Expression where file_name LIKE \'%%%s\' and end_lineno >= %d",
175 file_name, scope_end) == -1)
176 {
177 fprintf(stderr,
178 "Memory allocation problem occurred during creating database query!\n");
179 return MONKEY_NO;
180 }
181
182 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
183 if (err)
184 {
185 fprintf(stderr,
186 "Error occurred while executing Database query. `%s'",
187 errMsg);
188 return MONKEY_NO;
189 }
190 return MONKEY_OK;
191}
192
193
194/**
195 * Return the line number of the end-of-scope for the expression indicated by start_line_no
196 *
197 * @param cntxt context containing the Expression Database handle
198 * @param file_name path to the file in which the expression in question exists
199 * @param start_line_no expression's line
200 * @param iter callback function, iterator for values returned from the Database
201 * @param iter_cls closure for the expression iterator, will contain the scope-end line number
202 * @return MONKEY_OK on success, MONKEY_NO on failure
203 */
204int
205MONKEY_EDB_get_expression_scope_end (struct MONKEY_EDB_Context
206 *cntxt, const char *file_name,
207 int start_line_no,
208 MONKEY_ExpressionIterator
209 iter, void *iter_cls)
210{
211 int err;
212 char *errMsg;
213 char *query;
214
215 if (MONKEY_asprintf
216 (&query,
217 "select min(end_lineno) from Expression where file_name LIKE \'%%%s\' and start_lineno = %d",
218 file_name, start_line_no) == -1)
219 {
220 fprintf(stderr,
221 "Memory allocation problem occurred during creating database query!\n");
222 return MONKEY_NO;
223 }
224
225 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
226 MONKEY_free (query);
227
228 if (err)
229 {
230 fprintf(stderr,
231 "Error occurred while executing Database query. `%s'",
232 errMsg);
233 return MONKEY_NO;
234 }
235 return MONKEY_OK;
236}
237
238
239int
240MONKEY_EDB_get_expression_scope_end_for_expression (struct MONKEY_EDB_Context
241 *cntxt, const char *file_name,
242 const char * expr_syntax,
243 MONKEY_ExpressionIterator
244 iter, void *iter_cls)
245{
246 int err;
247 char *errMsg;
248 char *query;
249
250 if (MONKEY_asprintf
251 (&query,
252 "select end_lineno from Expression where file_name LIKE \'%%%s\' and expr_syntax = %s",
253 file_name, expr_syntax) == -1)
254 {
255 fprintf(stderr,
256 "Memory allocation problem occurred during creating database query!\n");
257 return MONKEY_NO;
258 }
259
260 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
261 MONKEY_free (query);
262
263 if (err)
264 {
265 fprintf(stderr,
266 "Error occurred while executing Database query. `%s'",
267 errMsg);
268 return MONKEY_NO;
269 }
270 return MONKEY_OK;
271}
272
273
274int
275MONKEY_EDB_get_globals( struct MONKEY_EDB_Context *cntxt,
276 const char *file_names,
277 MONKEY_ExpressionIterator iter,
278 void *iter_cls) {
279 int ret = MONKEY_OK;
280 char *errMsg;
281 char *query;
282 if( MONKEY_asprintf(&query,
283 "SELECT DISTINCT expr_syntax, is_call FROM Expression WHERE (%s) AND start_lineno = 0 AND end_lineno = 32767",
284 file_names) == -1 ) {
285 fprintf(stderr, "Memory allocation problem occurred!\n");
286 ret = MONKEY_NO;
287 goto fin;
288 }
289
290 if( sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg) ) {
291 fprintf(stderr, "Error occurred while executing Database query. `%s'", errMsg);
292 ret = MONKEY_NO;
293 goto fin;
294 }
295fin:
296 MONKEY_free_non_null(query);
297 return MONKEY_NO;
298}
299
300/**
301 * Run an SQLite query to retrieve those expressions that are previous to
302 * given expression and are in the same function of the given expression
303 *
304 * @param cntxt context containing the Expression Database handle
305 * @param file_name path to the file in which the expression in question exists
306 * @param start_line_no expression beginning line
307 * @param iter callback function, iterator for expressions returned from the Database
308 * @param iter_cls closure for the expression iterator
309 * @return MONKEY_OK success, MONKEY_NO failure
310 */
311int
312MONKEY_EDB_get_expressions (struct MONKEY_EDB_Context *cntxt,
313 const char *file_name, int start_line_no,
314 MONKEY_ExpressionIterator iter,
315 void *iter_cls)
316{
317 int err;
318 char *errMsg;
319 char *query;
320 if (MONKEY_asprintf
321 (&query,
322 "select distinct expr_syntax, is_call from Expression where file_name LIKE \'%%%s\' and start_lineno <= %d and end_lineno >= %d and end_lineno != 32767",
323 file_name, start_line_no, start_line_no) == -1)
324 {
325 fprintf(stderr, "Memory allocation problem occurred!\n");
326 return MONKEY_NO;
327 }
328
329 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
330 if (err)
331 {
332 fprintf(stderr, "Error occurred while executing Database query. `%s'\n", errMsg);
333 return MONKEY_NO;
334 }
335 return MONKEY_OK;
336}
337
338
339int
340MONKEY_EDB_get_sub_expressions (struct MONKEY_EDB_Context
341 *cntxt, const char *file_name,
342 int start_line_no, int end_line_no,
343 MONKEY_ExpressionIterator iter,
344 void *iter_cls)
345{
346 int err;
347 char *errMsg;
348 char *query;
349 if (MONKEY_asprintf
350 (&query,
351 "select expr_syntax, start_lineno, is_call from Expression where file_name LIKE \'%%%s\' and start_lineno = %d and end_lineno = %d",
352 file_name, start_line_no, end_line_no) == -1)
353 {
354 fprintf(stderr,
355 "Memory allocation problem occurred!\n");
356 return MONKEY_NO;
357 }
358
359 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
360 if (err)
361 {
362 fprintf(stderr,
363 "Error occurred while executing Database query. `%s'",
364 errMsg);
365 return MONKEY_NO;
366 }
367 return MONKEY_OK;
368}
diff --git a/pathologist/src/pathologist/getopt.c b/pathologist/src/pathologist/getopt.c
new file mode 100644
index 0000000..d7a037c
--- /dev/null
+++ b/pathologist/src/pathologist/getopt.c
@@ -0,0 +1,1047 @@
1/* Getopt for GNU.
2 NOTE: getopt is now part of the C library, so if you don't know what
3 "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4 before changing it!
5
6 Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
7 Free Software Foundation, Inc.
8
9NOTE: The canonical source of this file is maintained with the GNU C Library.
10Bugs can be reported to bug-glibc@prep.ai.mit.edu.
11
12This program is free software; you can redistribute it and/or modify it
13under the terms of the GNU General Public License as published by the
14Free Software Foundation; either version 2, or (at your option) any
15later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25USA.
26
27
28This code was heavily modified for GNUnet.
29Copyright (C) 2006 Christian Grothoff
30*/
31
32/**
33 * @file util/getopt.c
34 * @brief GNU style option parsing
35 *
36 * TODO: get rid of statics (make reentrant) and
37 * replace main GNU getopt parser with one that
38 * actually fits our API.
39 */
40
41#include "platform.h"
42#include "monkey_common.h"
43#include "monkey_getopt_lib.h"
44
45#ifdef VMS
46#include <unixlib.h>
47#if HAVE_STRING_H - 0
48#include <string.h>
49#endif
50#endif
51
52#define LOG(kind,...) MONKEY_log_from (kind, "util", __VA_ARGS__)
53
54#define LOG_STRERROR(kind,syscall) MONKEY_log_from_strerror (kind, "util", syscall)
55
56#if defined (WIN32) && !defined (__CYGWIN32__)
57/* It's not Unix, really. See? Capital letters. */
58#include <windows.h>
59#define getpid() GetCurrentProcessId()
60#endif
61
62#ifndef _
63/* This is for other GNU distributions with internationalized messages.
64 When compiling libc, the _ macro is predefined. */
65#ifdef HAVE_LIBINTL_H
66#include <libintl.h>
67#define _(msgid) gettext (msgid)
68#else
69#define _(msgid) (msgid)
70#endif
71#endif
72
73/* Describe the long-named options requested by the application.
74 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
75 of `struct GNoption' terminated by an element containing a name which is
76 zero.
77
78 The field `has_arg' is:
79 no_argument (or 0) if the option does not take an argument,
80 required_argument (or 1) if the option requires an argument,
81 optional_argument (or 2) if the option takes an optional argument.
82
83 If the field `flag' is not NULL, it points to a variable that is set
84 to the value given in the field `val' when the option is found, but
85 left unchanged if the option is not found.
86
87 To have a long-named option do something other than set an `int' to
88 a compiled-in constant, such as set a value from `GNoptarg', set the
89 option's `flag' field to zero and its `val' field to a nonzero
90 value (the equivalent single-letter option character, if there is
91 one). For long options that have a zero `flag' field, `getopt'
92 returns the contents of the `val' field. */
93
94struct GNoption
95{
96 const char *name;
97 /* has_arg can't be an enum because some compilers complain about
98 * type mismatches in all the code that assumes it is an int. */
99 int has_arg;
100 int *flag;
101 int val;
102};
103
104
105/* This version of `getopt' appears to the caller like standard Unix `getopt'
106 but it behaves differently for the user, since it allows the user
107 to intersperse the options with the other arguments.
108
109 As `getopt' works, it permutes the elements of ARGV so that,
110 when it is done, all the options precede everything else. Thus
111 all application programs are extended to handle flexible argument order.
112
113 Setting the environment variable POSIXLY_CORRECT disables permutation.
114 Then the behavior is completely standard.
115
116 GNU application programs can use a third alternative mode in which
117 they can distinguish the relative order of options and other arguments. */
118
119/* For communication from `getopt' to the caller.
120 When `getopt' finds an option that takes an argument,
121 the argument value is returned here.
122 Also, when `ordering' is RETURN_IN_ORDER,
123 each non-option ARGV-element is returned here. */
124
125static char *GNoptarg = NULL;
126
127/* Index in ARGV of the next element to be scanned.
128 This is used for communication to and from the caller
129 and for communication between successive calls to `getopt'.
130
131 On entry to `getopt', zero means this is the first call; initialize.
132
133 When `getopt' returns -1, this is the index of the first of the
134 non-option elements that the caller should itself scan.
135
136 Otherwise, `GNoptind' communicates from one call to the next
137 how much of ARGV has been scanned so far. */
138
139/* 1003.2 says this must be 1 before any call. */
140static int GNoptind = 1;
141
142/* The next char to be scanned in the option-element
143 in which the last option character we returned was found.
144 This allows us to pick up the scan where we left off.
145
146 If this is zero, or a null string, it means resume the scan
147 by advancing to the next ARGV-element. */
148
149static char *nextchar;
150
151
152/* Describe how to deal with options that follow non-option ARGV-elements.
153
154 If the caller did not specify anything,
155 the default is REQUIRE_ORDER if the environment variable
156 POSIXLY_CORRECT is defined, PERMUTE otherwise.
157
158 REQUIRE_ORDER means don't recognize them as options;
159 stop option processing when the first non-option is seen.
160 This is what Unix does.
161 This mode of operation is selected by either setting the environment
162 variable POSIXLY_CORRECT, or using `+' as the first character
163 of the list of option characters.
164
165 PERMUTE is the default. We MONKEY_CRYPTO_random_permute the contents of ARGV as we scan,
166 so that eventually all the non-options are at the end. This allows options
167 to be given in any order, even with programs that were not written to
168 expect this.
169
170 RETURN_IN_ORDER is an option available to programs that were written
171 to expect GNoptions and other ARGV-elements in any order and that care about
172 the ordering of the two. We describe each non-option ARGV-element
173 as if it were the argument of an option with character code 1.
174 Using `-' as the first character of the list of option characters
175 selects this mode of operation.
176
177 The special argument `--' forces an end of option-scanning regardless
178 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
179 `--' can cause `getopt' to return -1 with `GNoptind' != ARGC. */
180
181static enum
182{
183 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
184} ordering;
185
186/* Value of POSIXLY_CORRECT environment variable. */
187static char *posixly_correct;
188
189#ifdef __GNU_LIBRARY__
190/* We want to avoid inclusion of string.h with non-GNU libraries
191 because there are many ways it can cause trouble.
192 On some systems, it contains special magic macros that don't work
193 in GCC. */
194#include <string.h>
195#define my_index strchr
196#else
197
198/* Avoid depending on library functions or files
199 whose names are inconsistent. */
200
201char *
202getenv ();
203
204static char *
205my_index (const char *str,
206 int chr)
207{
208 while (*str)
209 {
210 if (*str == chr)
211 return (char *) str;
212 str++;
213 }
214 return 0;
215}
216
217/* If using GCC, we can safely declare strlen this way.
218 If not using GCC, it is ok not to declare it. */
219#ifdef __GNUC__
220/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
221 That was relevant to code that was here before. */
222#if !defined (__STDC__) || !__STDC__
223/* gcc with -traditional declares the built-in strlen to return int,
224 and has done so at least since version 2.4.5. -- rms. */
225extern int
226strlen (const char *);
227#endif /* not __STDC__ */
228#endif /* __GNUC__ */
229
230#endif /* not __GNU_LIBRARY__ */
231
232/* Handle permutation of arguments. */
233
234/* Describe the part of ARGV that contains non-options that have
235 been skipped. `first_nonopt' is the index in ARGV of the first of them;
236 `last_nonopt' is the index after the last of them. */
237
238static int first_nonopt;
239static int last_nonopt;
240
241#ifdef _LIBC
242/* Bash 2.0 gives us an environment variable containing flags
243 indicating ARGV elements that should not be considered arguments. */
244
245/* Defined in getopt_init.c */
246extern char *__getopt_nonoption_flags;
247
248static int nonoption_flags_max_len;
249static int nonoption_flags_len;
250
251static int original_argc;
252static char *const *original_argv;
253
254extern pid_t __libc_pid;
255
256/* Make sure the environment variable bash 2.0 puts in the environment
257 is valid for the getopt call we must make sure that the ARGV passed
258 to getopt is that one passed to the process. */
259static void MONKEY_UNUSED
260store_args_and_env (int argc, char *const *argv)
261{
262 /* XXX This is no good solution. We should rather copy the args so
263 * that we can compare them later. But we must not use malloc(3). */
264 original_argc = argc;
265 original_argv = argv;
266}
267
268text_set_element (__libc_subinit, store_args_and_env);
269
270#define SWAP_FLAGS(ch1, ch2) \
271 if (nonoption_flags_len > 0) \
272 { \
273 char __tmp = __getopt_nonoption_flags[ch1]; \
274 __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
275 __getopt_nonoption_flags[ch2] = __tmp; \
276 }
277#else /* !_LIBC */
278#define SWAP_FLAGS(ch1, ch2)
279#endif /* _LIBC */
280
281/* Exchange two adjacent subsequences of ARGV.
282 One subsequence is elements [first_nonopt,last_nonopt)
283 which contains all the non-options that have been skipped so far.
284 The other is elements [last_nonopt,GNoptind), which contains all
285 the options processed since those non-options were skipped.
286
287 `first_nonopt' and `last_nonopt' are relocated so that they describe
288 the new indices of the non-options in ARGV after they are moved. */
289
290#if defined (__STDC__) && __STDC__
291static void
292exchange (char **);
293#endif
294
295static void
296exchange (char **argv)
297{
298 int bottom = first_nonopt;
299 int middle = last_nonopt;
300 int top = GNoptind;
301 char *tem;
302
303 /* Exchange the shorter segment with the far end of the longer segment.
304 * That puts the shorter segment into the right place.
305 * It leaves the longer segment in the right place overall,
306 * but it consists of two parts that need to be swapped next. */
307
308#ifdef _LIBC
309 /* First make sure the handling of the `__getopt_nonoption_flags'
310 * string can work normally. Our top argument must be in the range
311 * of the string. */
312 if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
313 {
314 /* We must extend the array. The user plays games with us and
315 * presents new arguments. */
316 char *new_str = malloc (top + 1);
317
318 if (new_str == NULL)
319 nonoption_flags_len = nonoption_flags_max_len = 0;
320 else
321 {
322 memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
323 memset (&new_str[nonoption_flags_max_len], '\0',
324 top + 1 - nonoption_flags_max_len);
325 nonoption_flags_max_len = top + 1;
326 __getopt_nonoption_flags = new_str;
327 }
328 }
329#endif
330
331 while (top > middle && middle > bottom)
332 {
333 if (top - middle > middle - bottom)
334 {
335 /* Bottom segment is the short one. */
336 int len = middle - bottom;
337 register int i;
338
339 /* Swap it with the top part of the top segment. */
340 for (i = 0; i < len; i++)
341 {
342 tem = argv[bottom + i];
343 argv[bottom + i] = argv[top - (middle - bottom) + i];
344 argv[top - (middle - bottom) + i] = tem;
345 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
346 }
347 /* Exclude the moved bottom segment from further swapping. */
348 top -= len;
349 }
350 else
351 {
352 /* Top segment is the short one. */
353 int len = top - middle;
354 register int i;
355
356 /* Swap it with the bottom part of the bottom segment. */
357 for (i = 0; i < len; i++)
358 {
359 tem = argv[bottom + i];
360 argv[bottom + i] = argv[middle + i];
361 argv[middle + i] = tem;
362 SWAP_FLAGS (bottom + i, middle + i);
363 }
364 /* Exclude the moved top segment from further swapping. */
365 bottom += len;
366 }
367 }
368
369 /* Update records for the slots the non-options now occupy. */
370
371 first_nonopt += (GNoptind - last_nonopt);
372 last_nonopt = GNoptind;
373}
374
375/* Initialize the internal data when the first call is made. */
376
377#if defined (__STDC__) && __STDC__
378static const char *
379_getopt_initialize (int, char *const *, const char *);
380#endif
381static const char *
382_getopt_initialize (int argc,
383 char *const *argv,
384 const char *optstring)
385{
386 /* Start processing options with ARGV-element 1 (since ARGV-element 0
387 * is the program name); the sequence of previously skipped
388 * non-option ARGV-elements is empty. */
389
390 first_nonopt = last_nonopt = GNoptind;
391
392 nextchar = NULL;
393
394 posixly_correct = getenv ("POSIXLY_CORRECT");
395
396 /* Determine how to handle the ordering of options and nonoptions. */
397
398 if (optstring[0] == '-')
399 {
400 ordering = RETURN_IN_ORDER;
401 ++optstring;
402 }
403 else if (optstring[0] == '+')
404 {
405 ordering = REQUIRE_ORDER;
406 ++optstring;
407 }
408 else if (posixly_correct != NULL)
409 ordering = REQUIRE_ORDER;
410 else
411 ordering = PERMUTE;
412
413#ifdef _LIBC
414 if (posixly_correct == NULL && argc == original_argc && argv == original_argv)
415 {
416 if (nonoption_flags_max_len == 0)
417 {
418 if (__getopt_nonoption_flags == NULL ||
419 __getopt_nonoption_flags[0] == '\0')
420 nonoption_flags_max_len = -1;
421 else
422 {
423 const char *orig_str = __getopt_nonoption_flags;
424 int len = nonoption_flags_max_len = strlen (orig_str);
425
426 if (nonoption_flags_max_len < argc)
427 nonoption_flags_max_len = argc;
428 __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len);
429 if (__getopt_nonoption_flags == NULL)
430 nonoption_flags_max_len = -1;
431 else
432 {
433 memcpy (__getopt_nonoption_flags, orig_str, len);
434 memset (&__getopt_nonoption_flags[len], '\0',
435 nonoption_flags_max_len - len);
436 }
437 }
438 }
439 nonoption_flags_len = nonoption_flags_max_len;
440 }
441 else
442 nonoption_flags_len = 0;
443#endif
444
445 return optstring;
446}
447
448/* Scan elements of ARGV (whose length is ARGC) for option characters
449 given in OPTSTRING.
450
451 If an element of ARGV starts with '-', and is not exactly "-" or "--",
452 then it is an option element. The characters of this element
453 (aside from the initial '-') are option characters. If `getopt'
454 is called repeatedly, it returns successively each of the option characters
455 from each of the option elements.
456
457 If `getopt' finds another option character, it returns that character,
458 updating `GNoptind' and `nextchar' so that the next call to `getopt' can
459 resume the scan with the following option character or ARGV-element.
460
461 If there are no more option characters, `getopt' returns -1.
462 Then `GNoptind' is the index in ARGV of the first ARGV-element
463 that is not an option. (The ARGV-elements have been permuted
464 so that those that are not options now come last.)
465
466 OPTSTRING is a string containing the legitimate option characters.
467 If an option character is seen that is not listed in OPTSTRING,
468 return '?' after printing an error message. If you set `GNopterr' to
469 zero, the error message is suppressed but we still return '?'.
470
471 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
472 so the following text in the same ARGV-element, or the text of the following
473 ARGV-element, is returned in `GNoptarg'. Two colons mean an option that
474 wants an optional arg; if there is text in the current ARGV-element,
475 it is returned in `GNoptarg', otherwise `GNoptarg' is set to zero.
476
477 If OPTSTRING starts with `-' or `+', it requests different methods of
478 handling the non-option ARGV-elements.
479 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
480
481 Long-named options begin with `--' instead of `-'.
482 Their names may be abbreviated as long as the abbreviation is unique
483 or is an exact match for some defined option. If they have an
484 argument, it follows the option name in the same ARGV-element, separated
485 from the option name by a `=', or else the in next ARGV-element.
486 When `getopt' finds a long-named option, it returns 0 if that option's
487 `flag' field is nonzero, the value of the option's `val' field
488 if the `flag' field is zero.
489
490 The elements of ARGV aren't really const, because we MONKEY_CRYPTO_random_permute them.
491 But we pretend they're const in the prototype to be compatible
492 with other systems.
493
494 LONGOPTS is a vector of `struct GNoption' terminated by an
495 element containing a name which is zero.
496
497 LONGIND returns the index in LONGOPT of the long-named option found.
498 It is only valid when a long-named option has been found by the most
499 recent call.
500
501 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
502 long-named options. */
503
504static int
505GN_getopt_internal (int argc, char *const *argv, const char *optstring,
506 const struct GNoption *longopts, int *longind,
507 int long_only)
508{
509 static int __getopt_initialized = 0;
510 static int GNopterr = 1;
511
512 GNoptarg = NULL;
513
514 if (GNoptind == 0 || !__getopt_initialized)
515 {
516 if (GNoptind == 0)
517 GNoptind = 1; /* Don't scan ARGV[0], the program name. */
518 optstring = _getopt_initialize (argc, argv, optstring);
519 __getopt_initialized = 1;
520 }
521
522 /* Test whether ARGV[GNoptind] points to a non-option argument.
523 * Either it does not have option syntax, or there is an environment flag
524 * from the shell indicating it is not an option. The later information
525 * is only used when the used in the GNU libc. */
526#ifdef _LIBC
527#define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0' \
528 || (GNoptind < nonoption_flags_len \
529 && __getopt_nonoption_flags[GNoptind] == '1'))
530#else
531#define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
532#endif
533
534 if (nextchar == NULL || *nextchar == '\0')
535 {
536 /* Advance to the next ARGV-element. */
537
538 /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
539 * moved back by the user (who may also have changed the arguments). */
540 if (last_nonopt > GNoptind)
541 last_nonopt = GNoptind;
542 if (first_nonopt > GNoptind)
543 first_nonopt = GNoptind;
544
545 if (ordering == PERMUTE)
546 {
547 /* If we have just processed some options following some non-options,
548 * exchange them so that the options come first. */
549
550 if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
551 exchange ((char **) argv);
552 else if (last_nonopt != GNoptind)
553 first_nonopt = GNoptind;
554
555 /* Skip any additional non-options
556 * and extend the range of non-options previously skipped. */
557
558 while (GNoptind < argc && NONOPTION_P)
559 GNoptind++;
560 last_nonopt = GNoptind;
561 }
562
563 /* The special ARGV-element `--' means premature end of options.
564 * Skip it like a null option,
565 * then exchange with previous non-options as if it were an option,
566 * then skip everything else like a non-option. */
567 if (GNoptind != argc && !strcmp (argv[GNoptind], "--"))
568 {
569 GNoptind++;
570
571 if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
572 exchange ((char **) argv);
573 else if (first_nonopt == last_nonopt)
574 first_nonopt = GNoptind;
575 last_nonopt = argc;
576
577 GNoptind = argc;
578 }
579
580 /* If we have done all the ARGV-elements, stop the scan
581 * and back over any non-options that we skipped and permuted. */
582
583 if (GNoptind == argc)
584 {
585 /* Set the next-arg-index to point at the non-options
586 * that we previously skipped, so the caller will digest them. */
587 if (first_nonopt != last_nonopt)
588 GNoptind = first_nonopt;
589 return -1;
590 }
591
592 /* If we have come to a non-option and did not permute it,
593 * either stop the scan or describe it to the caller and pass it by. */
594
595 if (NONOPTION_P)
596 {
597 if (ordering == REQUIRE_ORDER)
598 return -1;
599 GNoptarg = argv[GNoptind++];
600 return 1;
601 }
602
603 /* We have found another option-ARGV-element.
604 * Skip the initial punctuation. */
605
606 nextchar =
607 (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-'));
608 }
609
610 /* Decode the current option-ARGV-element. */
611
612 /* Check whether the ARGV-element is a long option.
613 *
614 * If long_only and the ARGV-element has the form "-f", where f is
615 * a valid short option, don't consider it an abbreviated form of
616 * a long option that starts with f. Otherwise there would be no
617 * way to give the -f short option.
618 *
619 * On the other hand, if there's a long option "fubar" and
620 * the ARGV-element is "-fu", do consider that an abbreviation of
621 * the long option, just like "--fu", and not "-f" with arg "u".
622 *
623 * This distinction seems to be the most useful approach. */
624
625 if (longopts != NULL &&
626 (argv[GNoptind][1] == '-' ||
627 (long_only &&
628 (argv[GNoptind][2] || !my_index (optstring, argv[GNoptind][1])))))
629 {
630 char *nameend;
631 const struct GNoption *p;
632 const struct GNoption *pfound = NULL;
633 int exact = 0;
634 int ambig = 0;
635 int indfound = -1;
636 int option_index;
637
638 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
639 /* Do nothing. */ ;
640
641 /* Test all long options for either exact match
642 * or abbreviated matches. */
643 for (p = longopts, option_index = 0; p->name; p++, option_index++)
644 if (!strncmp (p->name, nextchar, nameend - nextchar))
645 {
646 if ((unsigned int) (nameend - nextchar) ==
647 (unsigned int) strlen (p->name))
648 {
649 /* Exact match found. */
650 pfound = p;
651 indfound = option_index;
652 exact = 1;
653 break;
654 }
655 else if (pfound == NULL)
656 {
657 /* First nonexact match found. */
658 pfound = p;
659 indfound = option_index;
660 }
661 else
662 /* Second or later nonexact match found. */
663 ambig = 1;
664 }
665
666 if (ambig && !exact)
667 {
668 if (GNopterr)
669 FPRINTF (stderr, _("%s: option `%s' is ambiguous\n"), argv[0],
670 argv[GNoptind]);
671 nextchar += strlen (nextchar);
672 GNoptind++;
673 return '?';
674 }
675
676 if (pfound != NULL)
677 {
678 option_index = indfound;
679 GNoptind++;
680 if (*nameend)
681 {
682 /* Don't test has_arg with >, because some C compilers don't
683 * allow it to be used on enums. */
684 if (pfound->has_arg)
685 GNoptarg = nameend + 1;
686 else
687 {
688 if (GNopterr)
689 {
690 if (argv[GNoptind - 1][1] == '-')
691 /* --option */
692 FPRINTF (stderr,
693 _("%s: option `--%s' does not allow an argument\n"),
694 argv[0], pfound->name);
695 else
696 /* +option or -option */
697 FPRINTF (stderr,
698 _("%s: option `%c%s' does not allow an argument\n"),
699 argv[0], argv[GNoptind - 1][0], pfound->name);
700 }
701 nextchar += strlen (nextchar);
702 return '?';
703 }
704 }
705 else if (pfound->has_arg == 1)
706 {
707 if (GNoptind < argc)
708 {
709 GNoptarg = argv[GNoptind++];
710 }
711 else
712 {
713 if (GNopterr)
714 {
715 FPRINTF (stderr, _("%s: option `%s' requires an argument\n"),
716 argv[0], argv[GNoptind - 1]);
717 }
718 nextchar += strlen (nextchar);
719 return (optstring[0] == ':') ? ':' : '?';
720 }
721 }
722 nextchar += strlen (nextchar);
723 if (longind != NULL)
724 *longind = option_index;
725 if (pfound->flag)
726 {
727 *(pfound->flag) = pfound->val;
728 return 0;
729 }
730 return pfound->val;
731 }
732
733 /* Can't find it as a long option. If this is not getopt_long_only,
734 * or the option starts with '--' or is not a valid short
735 * option, then it's an error.
736 * Otherwise interpret it as a short option. */
737 if (!long_only || argv[GNoptind][1] == '-' ||
738 my_index (optstring, *nextchar) == NULL)
739 {
740 if (GNopterr)
741 {
742 if (argv[GNoptind][1] == '-')
743 /* --option */
744 FPRINTF (stderr, _("%s: unrecognized option `--%s'\n"), argv[0],
745 nextchar);
746 else
747 /* +option or -option */
748 FPRINTF (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0],
749 argv[GNoptind][0], nextchar);
750 }
751 nextchar = (char *) "";
752 GNoptind++;
753 return '?';
754 }
755 }
756
757 /* Look at and handle the next short option-character. */
758
759 {
760 char c = *nextchar++;
761 char *temp = my_index (optstring, c);
762
763 /* Increment `GNoptind' when we start to process its last character. */
764 if (*nextchar == '\0')
765 ++GNoptind;
766
767 if (temp == NULL || c == ':')
768 {
769 if (GNopterr)
770 {
771 if (posixly_correct)
772 /* 1003.2 specifies the format of this message. */
773 FPRINTF (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
774 else
775 FPRINTF (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
776 }
777 return '?';
778 }
779 /* Convenience. Treat POSIX -W foo same as long option --foo */
780 if (temp[0] == 'W' && temp[1] == ';')
781 {
782 char *nameend;
783 const struct GNoption *p;
784 const struct GNoption *pfound = NULL;
785 int exact = 0;
786 int ambig = 0;
787 int indfound = 0;
788 int option_index;
789
790 /* This is an option that requires an argument. */
791 if (*nextchar != '\0')
792 {
793 GNoptarg = nextchar;
794 /* If we end this ARGV-element by taking the rest as an arg,
795 * we must advance to the next element now. */
796 GNoptind++;
797 }
798 else if (GNoptind == argc)
799 {
800 if (GNopterr)
801 {
802 /* 1003.2 specifies the format of this message. */
803 FPRINTF (stderr, _("%s: option requires an argument -- %c\n"),
804 argv[0], c);
805 }
806 if (optstring[0] == ':')
807 c = ':';
808 else
809 c = '?';
810 return c;
811 }
812 else
813 /* We already incremented `GNoptind' once;
814 * increment it again when taking next ARGV-elt as argument. */
815 GNoptarg = argv[GNoptind++];
816
817 /* GNoptarg is now the argument, see if it's in the
818 * table of longopts. */
819
820 for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
821 nameend++)
822 /* Do nothing. */ ;
823
824 /* Test all long options for either exact match
825 * or abbreviated matches. */
826 if (longopts != NULL)
827 for (p = longopts, option_index = 0; p->name; p++, option_index++)
828 if (!strncmp (p->name, nextchar, nameend - nextchar))
829 {
830 if ((unsigned int) (nameend - nextchar) == strlen (p->name))
831 {
832 /* Exact match found. */
833 pfound = p;
834 indfound = option_index;
835 exact = 1;
836 break;
837 }
838 else if (pfound == NULL)
839 {
840 /* First nonexact match found. */
841 pfound = p;
842 indfound = option_index;
843 }
844 else
845 /* Second or later nonexact match found. */
846 ambig = 1;
847 }
848 if (ambig && !exact)
849 {
850 if (GNopterr)
851 FPRINTF (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0],
852 argv[GNoptind]);
853 nextchar += strlen (nextchar);
854 GNoptind++;
855 return '?';
856 }
857 if (pfound != NULL)
858 {
859 option_index = indfound;
860 if (*nameend)
861 {
862 /* Don't test has_arg with >, because some C compilers don't
863 * allow it to be used on enums. */
864 if (pfound->has_arg)
865 GNoptarg = nameend + 1;
866 else
867 {
868 if (GNopterr)
869 FPRINTF (stderr, _("\
870%s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name);
871
872 nextchar += strlen (nextchar);
873 return '?';
874 }
875 }
876 else if (pfound->has_arg == 1)
877 {
878 if (GNoptind < argc)
879 GNoptarg = argv[GNoptind++];
880 else
881 {
882 if (GNopterr)
883 FPRINTF (stderr, _("%s: option `%s' requires an argument\n"),
884 argv[0], argv[GNoptind - 1]);
885 nextchar += strlen (nextchar);
886 return optstring[0] == ':' ? ':' : '?';
887 }
888 }
889 nextchar += strlen (nextchar);
890 if (longind != NULL)
891 *longind = option_index;
892 if (pfound->flag)
893 {
894 *(pfound->flag) = pfound->val;
895 return 0;
896 }
897 return pfound->val;
898 }
899 nextchar = NULL;
900 return 'W'; /* Let the application handle it. */
901 }
902 if (temp[1] == ':')
903 {
904 if (temp[2] == ':')
905 {
906 /* This is an option that accepts an argument optionally. */
907 if (*nextchar != '\0')
908 {
909 GNoptarg = nextchar;
910 GNoptind++;
911 }
912 else
913 GNoptarg = NULL;
914 nextchar = NULL;
915 }
916 else
917 {
918 /* This is an option that requires an argument. */
919 if (*nextchar != '\0')
920 {
921 GNoptarg = nextchar;
922 /* If we end this ARGV-element by taking the rest as an arg,
923 * we must advance to the next element now. */
924 GNoptind++;
925 }
926 else if (GNoptind == argc)
927 {
928 if (GNopterr)
929 {
930 /* 1003.2 specifies the format of this message. */
931 FPRINTF (stderr, _("%s: option requires an argument -- %c\n"),
932 argv[0], c);
933 }
934 if (optstring[0] == ':')
935 c = ':';
936 else
937 c = '?';
938 }
939 else
940 /* We already incremented `GNoptind' once;
941 * increment it again when taking next ARGV-elt as argument. */
942 GNoptarg = argv[GNoptind++];
943 nextchar = NULL;
944 }
945 }
946 return c;
947 }
948}
949
950static int
951GNgetopt_long (int argc, char *const *argv, const char *options,
952 const struct GNoption *long_options, int *opt_index)
953{
954 return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
955}
956
957/* ******************** now the GNUnet specific modifications... ********************* */
958
959/**
960 * Parse the command line.
961 *
962 * @param binaryOptions Name of application with option summary
963 * @param allOptions defined options and handlers
964 * @param argc number of arguments
965 * @param argv actual arguments
966 * @return index into argv with first non-option
967 * argument, or -1 on error
968 */
969int
970MONKEY_GETOPT_run (const char *binaryOptions,
971 const struct MONKEY_GETOPT_CommandLineOption *allOptions,
972 unsigned int argc, char *const *argv)
973{
974 struct GNoption *long_options;
975 struct MONKEY_GETOPT_CommandLineProcessorContext clpc;
976 int count;
977 int i;
978 char *shorts;
979 int spos;
980 int cont;
981 int c;
982
983// MONKEY_assert (argc > 0);
984 GNoptind = 0;
985 clpc.binaryName = argv[0];
986 clpc.binaryOptions = binaryOptions;
987 clpc.allOptions = allOptions;
988 clpc.argv = argv;
989 clpc.argc = argc;
990 count = 0;
991 while (allOptions[count].name != NULL)
992 count++;
993 long_options = malloc (sizeof (struct GNoption) * (count + 1));
994 shorts = malloc (count * 2 + 1);
995 spos = 0;
996 for (i = 0; i < count; i++)
997 {
998 long_options[i].name = allOptions[i].name;
999 long_options[i].has_arg = allOptions[i].require_argument;
1000 long_options[i].flag = NULL;
1001 long_options[i].val = allOptions[i].shortName;
1002 shorts[spos++] = allOptions[i].shortName;
1003 if (allOptions[i].require_argument != 0)
1004 shorts[spos++] = ':';
1005 }
1006 long_options[count].name = NULL;
1007 long_options[count].has_arg = 0;
1008 long_options[count].flag = NULL;
1009 long_options[count].val = '\0';
1010 shorts[spos] = '\0';
1011 cont = MONKEY_OK;
1012 /* main getopt loop */
1013 while (cont == MONKEY_OK)
1014 {
1015 int option_index = 0;
1016
1017 c = GNgetopt_long (argc, argv, shorts, long_options, &option_index);
1018
1019 if (c == MONKEY_SYSERR)
1020 break; /* No more flags to process */
1021
1022 for (i = 0; i < count; i++)
1023 {
1024 clpc.currentArgument = GNoptind - 1;
1025 if ((char) c == allOptions[i].shortName)
1026 {
1027 cont =
1028 allOptions[i].processor (&clpc, allOptions[i].scls,
1029 allOptions[i].name, GNoptarg);
1030 break;
1031 }
1032 }
1033 if (i == count)
1034 {
1035 FPRINTF (stderr, _("Use %s to get a list of options.\n"), "--help");
1036 cont = MONKEY_SYSERR;
1037 }
1038 }
1039
1040 free (shorts);
1041 free (long_options);
1042 if (cont == MONKEY_SYSERR)
1043 return MONKEY_SYSERR;
1044 return GNoptind;
1045}
1046
1047/* end of getopt.c */
diff --git a/pathologist/src/pathologist/getopt_helpers.c b/pathologist/src/pathologist/getopt_helpers.c
new file mode 100644
index 0000000..50d02d8
--- /dev/null
+++ b/pathologist/src/pathologist/getopt_helpers.c
@@ -0,0 +1,294 @@
1/*
2 This file is part of GNUnet
3 (C) 2006, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/util/getopt_helpers.c
23 * @brief implements command line that sets option
24 * @author Christian Grothoff
25 */
26
27#include <string.h>
28#include "platform.h"
29#include "monkey_common.h"
30#include "monkey_getopt_lib.h"
31
32#define LOG(kind,...) MONKEY_log_from (kind, "util", __VA_ARGS__)
33
34
35/**
36 * Print out program version (implements --version).
37 *
38 * @param ctx command line processing context
39 * @param scls additional closure (points to version string)
40 * @param option name of the option
41 * @param value not used (NULL)
42 * @return MONKEY_SYSERR (do not continue)
43 */
44int
45MONKEY_GETOPT_print_version_ (struct MONKEY_GETOPT_CommandLineProcessorContext
46 *ctx, void *scls, const char *option,
47 const char *value)
48{
49 const char *version = scls;
50
51 printf ("%s v%s\n", ctx->binaryName, version);
52 return MONKEY_SYSERR;
53}
54
55
56
57#define BORDER 29
58
59/**
60 * Print out details on command line options (implements --help).
61 *
62 * @param ctx command line processing context
63 * @param scls additional closure (points to about text)
64 * @param option name of the option
65 * @param value not used (NULL)
66 * @return MONKEY_SYSERR (do not continue)
67 */
68int
69MONKEY_GETOPT_format_help_ (struct MONKEY_GETOPT_CommandLineProcessorContext
70 *ctx, void *scls, const char *option,
71 const char *value)
72{
73 const char *about = scls;
74 size_t slen;
75 unsigned int i;
76 int j;
77 size_t ml;
78 size_t p;
79 char *scp;
80 const char *trans;
81 const struct MONKEY_GETOPT_CommandLineOption *opt;
82
83 if (NULL != about)
84 {
85 printf ("%s\n%s\n", ctx->binaryOptions, about);
86 printf ("Arguments mandatory for long options are also mandatory for short options.\n");
87 }
88 i = 0;
89 opt = ctx->allOptions;
90 while (opt[i].description != NULL)
91 {
92 if (opt[i].shortName == '\0')
93 printf (" ");
94 else
95 printf (" -%c, ", opt[i].shortName);
96 printf ("--%s", opt[i].name);
97 slen = 8 + strlen (opt[i].name);
98 if (opt[i].argumentHelp != NULL)
99 {
100 printf ("=%s", opt[i].argumentHelp);
101 slen += 1 + strlen (opt[i].argumentHelp);
102 }
103 if (slen > BORDER)
104 {
105 printf ("\n%*s", BORDER, "");
106 slen = BORDER;
107 }
108 if (slen < BORDER)
109 {
110 printf ("%*s", (int) (BORDER - slen), "");
111 slen = BORDER;
112 }
113 if (0 < strlen (opt[i].description))
114 trans = opt[i].description;
115 else
116 trans = "";
117 ml = strlen (trans);
118 p = 0;
119OUTER:
120 while (ml - p > 78 - slen)
121 {
122 for (j = p + 78 - slen; j > p; j--)
123 {
124 if (isspace ((unsigned char) trans[j]))
125 {
126 scp = malloc (j - p + 1);
127 memcpy (scp, &trans[p], j - p);
128 scp[j - p] = '\0';
129 printf ("%s\n%*s", scp, BORDER + 2, "");
130 free (scp);
131 p = j + 1;
132 slen = BORDER + 2;
133 goto OUTER;
134 }
135 }
136 /* could not find space to break line */
137 scp = malloc (78 - slen + 1);
138 memcpy (scp, &trans[p], 78 - slen);
139 scp[78 - slen] = '\0';
140 printf ("%s\n%*s", scp, BORDER + 2, "");
141 free (scp);
142 slen = BORDER + 2;
143 p = p + 78 - slen;
144 }
145 /* print rest */
146 if (p < ml)
147 printf ("%s\n", &trans[p]);
148 if (strlen (trans) == 0)
149 printf ("\n");
150 i++;
151 }
152 printf ("Report bugs to gnunet-developers@gnu.org.\n"
153 "GNUnet home page: http://www.gnu.org/software/gnunet/\n"
154 "General help using GNU software: http://www.gnu.org/gethelp/\n");
155 return MONKEY_SYSERR;
156}
157
158
159/**
160 * Set an option of type 'unsigned int' from the command line. Each
161 * time the option flag is given, the value is incremented by one.
162 * A pointer to this function should be passed as part of the
163 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
164 * of this type. It should be followed by a pointer to a value of
165 * type 'int'.
166 *
167 * @param ctx command line processing context
168 * @param scls additional closure (will point to the 'int')
169 * @param option name of the option
170 * @param value not used (NULL)
171 * @return MONKEY_OK
172 */
173int
174MONKEY_GETOPT_increment_value (struct MONKEY_GETOPT_CommandLineProcessorContext
175 *ctx, void *scls, const char *option,
176 const char *value)
177{
178 int *val = scls;
179
180 (*val)++;
181 return MONKEY_OK;
182}
183
184
185/**
186 * Set an option of type 'int' from the command line to 1 if the
187 * given option is present.
188 * A pointer to this function should be passed as part of the
189 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
190 * of this type. It should be followed by a pointer to a value of
191 * type 'int'.
192 *
193 * @param ctx command line processing context
194 * @param scls additional closure (will point to the 'int')
195 * @param option name of the option
196 * @param value not used (NULL)
197 * @return MONKEY_OK
198 */
199int
200MONKEY_GETOPT_set_one (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
201 void *scls, const char *option, const char *value)
202{
203 int *val = scls;
204
205 *val = 1;
206 return MONKEY_OK;
207}
208
209
210/**
211 * Set an option of type 'char *' from the command line.
212 * A pointer to this function should be passed as part of the
213 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
214 * of this type. It should be followed by a pointer to a value of
215 * type 'char *'.
216 *
217 * @param ctx command line processing context
218 * @param scls additional closure (will point to the 'char *',
219 * which will be allocated)
220 * @param option name of the option
221 * @param value actual value of the option (a string)
222 * @return MONKEY_OK
223 */
224int
225MONKEY_GETOPT_set_string (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
226 void *scls, const char *option, const char *value)
227{
228 char **val = scls;
229
230// MONKEY_assert (value != NULL);
231// MONKEY_free_non_null (*val);
232 if(*val != NULL) free(*val);
233 *val = strdup (value);
234 return MONKEY_OK;
235}
236
237
238/**
239 * Set an option of type 'unsigned long long' from the command line.
240 * A pointer to this function should be passed as part of the
241 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
242 * of this type. It should be followed by a pointer to a value of
243 * type 'unsigned long long'.
244 *
245 * @param ctx command line processing context
246 * @param scls additional closure (will point to the 'unsigned long long')
247 * @param option name of the option
248 * @param value actual value of the option as a string.
249 * @return MONKEY_OK if parsing the value worked
250 */
251int
252MONKEY_GETOPT_set_ulong (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
253 void *scls, const char *option, const char *value)
254{
255 unsigned long long *val = scls;
256
257 if (1 != SSCANF (value, "%llu", val))
258 {
259 FPRINTF (stderr, "You must pass a number to the `%s' option.\n", option);
260 return MONKEY_SYSERR;
261 }
262 return MONKEY_OK;
263}
264
265
266/**
267 * Set an option of type 'unsigned int' from the command line.
268 * A pointer to this function should be passed as part of the
269 * 'struct MONKEY_GETOPT_CommandLineOption' array to initialize options
270 * of this type. It should be followed by a pointer to a value of
271 * type 'unsigned int'.
272 *
273 * @param ctx command line processing context
274 * @param scls additional closure (will point to the 'unsigned int')
275 * @param option name of the option
276 * @param value actual value of the option as a string.
277 * @return MONKEY_OK if parsing the value worked
278 */
279int
280MONKEY_GETOPT_set_uint (struct MONKEY_GETOPT_CommandLineProcessorContext *ctx,
281 void *scls, const char *option, const char *value)
282{
283 unsigned int *val = scls;
284
285 if (1 != SSCANF (value, "%u", val))
286 {
287 FPRINTF (stderr, "You must pass a number to the `%s' option.\n", option);
288 return MONKEY_SYSERR;
289 }
290 return MONKEY_OK;
291}
292
293
294/* end of getopt_helpers.c */
diff --git a/pathologist/src/pathologist/mail_sender.c b/pathologist/src/pathologist/mail_sender.c
new file mode 100644
index 0000000..98edf84
--- /dev/null
+++ b/pathologist/src/pathologist/mail_sender.c
@@ -0,0 +1,231 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <ctype.h>
4#include <unistd.h>
5#include <getopt.h>
6#include <string.h>
7#include <fcntl.h>
8#include <signal.h>
9#include <errno.h>
10#include <stdarg.h>
11
12#include <openssl/ssl.h>
13#include <auth-client.h>
14#include <libesmtp.h>
15
16#if !defined (__GNUC__) || __GNUC__ < 2
17# define __attribute__(x)
18#endif
19
20
21int
22handle_invalid_peer_certificate(long vfy_result)
23{
24 const char *k ="rare error";
25 switch(vfy_result) {
26 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
27 k="X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"; break;
28 case X509_V_ERR_UNABLE_TO_GET_CRL:
29 k="X509_V_ERR_UNABLE_TO_GET_CRL"; break;
30 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
31 k="X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"; break;
32 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
33 k="X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"; break;
34 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
35 k="X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"; break;
36 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
37 k="X509_V_ERR_CERT_SIGNATURE_FAILURE"; break;
38 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
39 k="X509_V_ERR_CRL_SIGNATURE_FAILURE"; break;
40 case X509_V_ERR_CERT_NOT_YET_VALID:
41 k="X509_V_ERR_CERT_NOT_YET_VALID"; break;
42 case X509_V_ERR_CERT_HAS_EXPIRED:
43 k="X509_V_ERR_CERT_HAS_EXPIRED"; break;
44 case X509_V_ERR_CRL_NOT_YET_VALID:
45 k="X509_V_ERR_CRL_NOT_YET_VALID"; break;
46 case X509_V_ERR_CRL_HAS_EXPIRED:
47 k="X509_V_ERR_CRL_HAS_EXPIRED"; break;
48 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
49 k="X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"; break;
50 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
51 k="X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"; break;
52 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
53 k="X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"; break;
54 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
55 k="X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"; break;
56 case X509_V_ERR_OUT_OF_MEM:
57 k="X509_V_ERR_OUT_OF_MEM"; break;
58 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
59 k="X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"; break;
60 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
61 k="X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"; break;
62 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
63 k="X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"; break;
64 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
65 k="X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"; break;
66 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
67 k="X509_V_ERR_CERT_CHAIN_TOO_LONG"; break;
68 case X509_V_ERR_CERT_REVOKED:
69 k="X509_V_ERR_CERT_REVOKED"; break;
70 case X509_V_ERR_INVALID_CA:
71 k="X509_V_ERR_INVALID_CA"; break;
72 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
73 k="X509_V_ERR_PATH_LENGTH_EXCEEDED"; break;
74 case X509_V_ERR_INVALID_PURPOSE:
75 k="X509_V_ERR_INVALID_PURPOSE"; break;
76 case X509_V_ERR_CERT_UNTRUSTED:
77 k="X509_V_ERR_CERT_UNTRUSTED"; break;
78 case X509_V_ERR_CERT_REJECTED:
79 k="X509_V_ERR_CERT_REJECTED"; break;
80 }
81 printf("SMTP_EV_INVALID_PEER_CERTIFICATE: %ld: %s\n", vfy_result, k);
82 return 1; /* Accept the problem */
83}
84
85
86void event_cb (smtp_session_t session, int event_no, void *arg,...)
87{
88 va_list alist;
89 int *ok;
90
91 va_start(alist, arg);
92 switch(event_no) {
93 case SMTP_EV_CONNECT:
94 case SMTP_EV_MAILSTATUS:
95 case SMTP_EV_RCPTSTATUS:
96 case SMTP_EV_MESSAGEDATA:
97 case SMTP_EV_MESSAGESENT:
98 case SMTP_EV_DISCONNECT: break;
99 case SMTP_EV_WEAK_CIPHER: {
100 int bits;
101 bits = va_arg(alist, long); ok = va_arg(alist, int*);
102 printf("SMTP_EV_WEAK_CIPHER, bits=%d - accepted.\n", bits);
103 *ok = 1; break;
104 }
105 case SMTP_EV_STARTTLS_OK:
106 puts("SMTP_EV_STARTTLS_OK - TLS started here."); break;
107 case SMTP_EV_INVALID_PEER_CERTIFICATE: {
108 long vfy_result;
109 vfy_result = va_arg(alist, long); ok = va_arg(alist, int*);
110 *ok = handle_invalid_peer_certificate(vfy_result);
111 break;
112 }
113 case SMTP_EV_NO_PEER_CERTIFICATE: {
114 ok = va_arg(alist, int*);
115 puts("SMTP_EV_NO_PEER_CERTIFICATE - accepted.");
116 *ok = 1; break;
117 }
118 case SMTP_EV_WRONG_PEER_CERTIFICATE: {
119 ok = va_arg(alist, int*);
120 puts("SMTP_EV_WRONG_PEER_CERTIFICATE - accepted.");
121 *ok = 1; break;
122 }
123 case SMTP_EV_NO_CLIENT_CERTIFICATE: {
124 ok = va_arg(alist, int*);
125 puts("SMTP_EV_NO_CLIENT_CERTIFICATE - accepted.");
126 *ok = 1; break;
127 }
128 default:
129 printf("Got event: %d - ignored.\n", event_no);
130 }
131 va_end(alist);
132}
133
134
135/* Callback to prnt the recipient status */
136void
137print_recipient_status (smtp_recipient_t recipient,
138 const char *mailbox, void *arg)
139{
140 const smtp_status_t *status;
141
142 status = smtp_recipient_status (recipient);
143 printf ("%s: %d %s", mailbox, status->code, status->text);
144}
145
146
147void sendMail(const char *messageContents, const char* reportFileName, const char *emailAddress)
148{
149 smtp_session_t session;
150 smtp_message_t message;
151 smtp_recipient_t recipient;
152 const smtp_status_t *status;
153 struct sigaction sa;
154 char *host = "localhost:25";
155 char *from = "monkey@gnunet.org";
156 char *subject = "Monkey bug report";
157 const char *recipient_address = emailAddress;
158 char tempFileName[1000];
159 int tempFd;
160 FILE *fp;
161 enum notify_flags notify = Notify_SUCCESS | Notify_FAILURE;
162
163 auth_client_init();
164 session = smtp_create_session();
165 message = smtp_add_message(session);
166
167 /* Ignore sigpipe */
168 sa.sa_handler = SIG_IGN;
169 sigemptyset(&sa.sa_mask);
170 sa.sa_flags = 0;
171 sigaction(SIGPIPE, &sa, NULL);
172
173
174 smtp_set_server(session, host);
175 smtp_set_eventcb(session, event_cb, NULL);
176
177 /* Set the reverse path for the mail envelope. (NULL is ok)
178 */
179 smtp_set_reverse_path(message, from);
180
181 /* Set the Subject: header. For no reason, we want the supplied subject
182 to override any subject line in the message headers. */
183 if (subject != NULL) {
184 smtp_set_header(message, "Subject", subject);
185 smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1);
186 }
187
188
189 /* Prepare message */
190 if (NULL == reportFileName) {
191 memset(tempFileName, 0, sizeof(tempFileName));
192 sprintf(tempFileName, "/tmp/messageXXXXXX");
193 tempFd = mkstemp(tempFileName);
194 fp = fdopen(tempFd, "w");
195 fprintf(fp, "%s", messageContents);
196 fclose(fp);
197 fp = fopen(tempFileName, "r");
198 smtp_set_message_fp(message, fp);
199 } else {
200 fp = fopen(reportFileName, "r");
201 smtp_set_message_fp(message, fp);
202 }
203
204
205 recipient = smtp_add_recipient(message, recipient_address);
206
207 smtp_dsn_set_notify (recipient, notify);
208
209 /* Initiate a connection to the SMTP server and transfer the
210 message. */
211 if (!smtp_start_session(session)) {
212 char buf[128];
213
214 fprintf(stderr, "SMTP server problem %s\n", smtp_strerror(smtp_errno(),
215 buf, sizeof buf));
216 } else {
217 /* Report on the success or otherwise of the mail transfer.
218 */
219 status = smtp_message_transfer_status(message);
220 printf("%d %s", status->code, (status->text != NULL) ? status->text
221 : "\n");
222 smtp_enumerate_recipients(message, print_recipient_status, NULL);
223 }
224
225 /* Free resources consumed by the program.
226 */
227 smtp_destroy_session(session);
228 fclose(fp);
229 auth_client_exit();
230}
231
diff --git a/pathologist/src/pathologist/pathologist.c b/pathologist/src/pathologist/pathologist.c
new file mode 100644
index 0000000..305c3ce
--- /dev/null
+++ b/pathologist/src/pathologist/pathologist.c
@@ -0,0 +1,357 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file pathologist/pathologist.c
23 * @brief Monkey Pathologist: automated debugging tool
24 */
25
26#include <stdio.h>
27#include <string.h>
28#include <unistd.h>
29#include <sys/stat.h>
30#include "monkey_common.h"
31#include "action.h"
32#include "monkey_getopt_lib.h"
33
34static char *dumpFileName;
35static char *binaryName;
36static char *command;
37static char *binaryArgs;
38static char *emailAddress;
39static char *edbFilePath;
40static char *gdbBinaryPath;
41static char *valgrindBinaryPath;
42static char *inspectExpression;
43static char *inspectFunction;
44static int scopeDepth;
45static int reverseExecutionAllowed = MONKEY_NO;
46static int ret = 0;
47
48static int checkFileExistence(const char *filePath) {
49 struct stat statBuff;
50 if (0 == stat(filePath, &statBuff)) {
51 return MONKEY_YES;
52 }
53 return MONKEY_NO;
54}
55
56
57static int checkELF(const char *binaryPath) {
58 int ch;
59 const char ELF[5] = {0x7f, 'E', 'L', 'F', '\0'}; // ELF magic number
60 char inputArr[5];
61 FILE *filePtr;
62 filePtr = fopen(binaryPath, "r");
63 int i;
64
65 for (i = 0; i < 4; i++) {
66 ch = fgetc(filePtr);
67 if (EOF == ch) {
68 return MONKEY_NO;
69 }
70 inputArr[i] = ch;
71 }
72 inputArr[4] = '\0';
73 if (strcmp(ELF, inputArr) == 0) {
74 return MONKEY_YES;
75 }
76 return MONKEY_NO;
77}
78/**
79 * Main function that will launch Pathologist's action api.
80*/
81static void run()
82{
83 int result;
84 struct MONKEY_ACTION_Context *cntxt;
85
86 /* Check files existence */
87 if (MONKEY_NO == checkFileExistence(binaryName)) {
88 fprintf(stderr, "Error: Target binary file does not exist.\n");
89 ret = 1;
90 return;
91 }
92
93 if (MONKEY_NO == checkFileExistence(edbFilePath)) {
94 fprintf(stderr, "Error: Expression database file does not exist.\n");
95 ret = 1;
96 return;
97 }
98
99 if (NULL != gdbBinaryPath &&
100 MONKEY_NO == checkFileExistence(gdbBinaryPath))
101 {
102 fprintf(stderr, "Error: gdb binary file does not exist.\n");
103 ret = 1;
104 return;
105
106 }
107
108 if (NULL != valgrindBinaryPath &&
109 MONKEY_NO == checkFileExistence(valgrindBinaryPath))
110 {
111 fprintf(stderr, "Error: valgrind binary file does not exist.\n");
112 ret = 1;
113 return;
114 }
115
116 /* Check if the target program is and ELF binary */
117 if (MONKEY_NO == checkELF(binaryName)) {
118 FILE* targetProgramPipe;
119 char buffer[128];
120 ret = 1;
121
122 fprintf(stderr, "Target program is not an ELF. Pathologist will not debug the program.\n");
123 fprintf(stderr, "Pathologist will attempt to run the program normally.\n");
124
125 targetProgramPipe = popen(command, "r");
126 if (NULL == targetProgramPipe) {
127 fprintf(stderr, "Target is not a binary.\n");
128 return;
129 }
130 while(!feof(targetProgramPipe)) {
131 if (NULL != fgets(buffer, 128, targetProgramPipe)) {
132 fputs(buffer, stderr);
133 }
134 }
135 pclose(targetProgramPipe);
136 return;
137 }
138
139 if (NULL == edbFilePath)
140 {
141 /* lookup a file named test.db in the working directory */
142 struct stat buf;
143 if (0 != stat ("test.db", &buf))
144 {
145 fprintf( stderr,
146 "Expression Database file was not provided as and argument, "
147 "and there is no file named test.db in pathologist's working directory!\n");
148 MONKEY_break (0);
149 ret = 1;
150 return;
151 }
152 }
153
154 if (NULL == dumpFileName)
155 {
156 /* if no file name provided for the output report, the default report name will be binaryName_PIDpid */
157 const char *bn = strrchr(binaryName, '/');
158 if (NULL == bn) {
159 bn = binaryName;
160 } else {
161 bn++;
162 }
163 MONKEY_asprintf(&dumpFileName, "%s_PID%d", bn, getpid());
164 }
165
166 /* Initialize context for the Action API */
167 cntxt = MONKEY_malloc (sizeof (struct MONKEY_ACTION_Context));
168 cntxt->email_address = emailAddress;
169 cntxt->binary_name = binaryName;
170 cntxt->binaryArgs = binaryArgs;
171 cntxt->expression_database_path = edbFilePath;
172 cntxt->gdb_binary_path = gdbBinaryPath;
173 cntxt->valgrind_binary_path = valgrindBinaryPath;
174 cntxt->inspect_expression = inspectExpression;
175 cntxt->inspect_function = inspectFunction;
176 cntxt->scope_depth = scopeDepth;
177 cntxt->bug_detected = NO_BUG_DETECTED;
178 cntxt->has_null = MONKEY_NO;
179 cntxt->xml_report_node = NULL;
180 cntxt->run_reverse = reverseExecutionAllowed;
181 cntxt->gdb_connected = MONKEY_NO;
182
183 result = MONKEY_ACTION_rerun_with_gdb (cntxt);
184 int retVal;
185 switch (result)
186 {
187 case MONKEY_NO:
188 case GDB_STATE_ERROR:
189 fprintf (stderr, "Error in using gdb. Pathologist will exit now!\n");
190 ret = 1;
191 break;
192 case GDB_STATE_EXIT_NORMALLY:
193 fprintf (stderr, "Debug with gdb, program exited normally!\n");
194 break;
195 case GDB_STATE_STOPPED:
196 //categorize bug
197 if ((strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Segmentation fault") == 0)
198 || (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Signal 0") == 0))
199 cntxt->bug_detected = MONKEY_ACTION_is_Nullpointer(cntxt) ? BUG_NULL_POINTER : BUG_BAD_MEM_ACCESS;
200 else if (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Aborted") == 0)
201 cntxt->bug_detected = BUG_ABORT;
202 else if (strcasecmp(cntxt->gdb_stop_reason->signal_meaning, "Arithmetic exception") == 0)
203 cntxt->bug_detected = BUG_ARITHMETIC;
204 else if (strcasecmp(cntxt->gdb_stop_reason->signal_name, "SIGBUS") == 0)
205 cntxt->bug_detected = BUG_SIG_BUS;
206
207 // get relevant expressions
208 retVal = MONKEY_ACTION_inspect_expression_database (cntxt);
209
210 if (MONKEY_NO == retVal)
211 {
212 fprintf( stderr,
213 "Error in using the expression database. Pathologist will exit now!\n");
214 ret = 1;
215 break;
216 }
217 else if (BUG_BAD_MEM_ACCESS == cntxt->bug_detected
218 || BUG_SIG_BUS == cntxt->bug_detected)
219 {
220 /* launch valgrind */
221 retVal = MONKEY_ACTION_rerun_with_valgrind (cntxt);
222 if (MONKEY_NO == retVal)
223 fprintf( stderr, "Error using Valgrind! Pathologist will continue debugging!\n");
224 }
225
226 /* Start backtracking if enabled by user */
227 if (cntxt->run_reverse) {
228 retVal = MONKEY_ACTION_start_reverse_execution(cntxt);
229 if (MONKEY_NO == retVal)
230 fprintf(stderr, "Error during Backtracking! Pathologist will continue debugging with backtracking.\n");
231 }
232
233
234 // REPORTING
235 if (MONKEY_OK != MONKEY_ACTION_format_report_xml (cntxt))
236 {
237 fprintf( stderr,
238 "Error in generating debug report!\n");
239 ret = 1;
240 }
241 if (emailAddress != NULL)
242 {
243 if (MONKEY_OK != MONKEY_ACTION_report_email (cntxt, dumpFileName))
244 {
245 fprintf( stderr, "Error sending email!\n");
246 ret = 1;
247 }
248 }
249 if (dumpFileName != NULL)
250 {
251 if (MONKEY_OK !=
252 MONKEY_ACTION_report_file (cntxt, dumpFileName, MONKEY_YES))
253 {
254 fprintf( stderr,
255 "Error in saving debug file!\n");
256 ret = 1;
257 }
258 }
259 break;
260 default:
261 break;
262 }
263
264MONKEY_ACTION_delete_context (cntxt);
265}
266
267
268int freePathologistArgs()
269{
270 if (NULL != dumpFileName)
271 MONKEY_free(dumpFileName);
272 if (NULL != emailAddress)
273 MONKEY_free(emailAddress);
274 if (NULL != edbFilePath)
275 MONKEY_free(edbFilePath);
276 if (NULL != gdbBinaryPath)
277 MONKEY_free(gdbBinaryPath);
278 if (NULL != valgrindBinaryPath)
279 MONKEY_free(valgrindBinaryPath);
280 if (NULL != inspectExpression)
281 MONKEY_free(inspectExpression);
282 if (NULL != inspectFunction)
283 MONKEY_free(inspectFunction);
284
285 return MONKEY_OK;
286}
287
288
289
290const char * buildBinaryArgs(int argc, char **argv) {
291 char * res = MONKEY_strdup("");
292 char * tmp;
293 int i;
294 for (i = 0; i < argc; i++) {
295 MONKEY_asprintf(&tmp, "%s %s", res, argv[i]);
296 MONKEY_free(res);
297 res = tmp;
298 }
299
300 return res;
301}
302
303int
304main (int argc, char *argv[])
305{
306 static const struct MONKEY_GETOPT_CommandLineOption options[] = {
307 {'d', "database", "FILENAME", "the expression database to use, generated by seaspider",
308 1, &MONKEY_GETOPT_set_string, &edbFilePath},
309 {'f', "function", "FUNCTIONNAME", "the name of the function, in which pathologist will set a breakpoint",
310 1, &MONKEY_GETOPT_set_string, &inspectFunction},
311 {'g', "gdb", "FILENAME", "path to gdb binary to use. If not passed, pathologist will set it to /usr/bin/gdb",
312 1, &MONKEY_GETOPT_set_string, &gdbBinaryPath},
313 {'h', "help", NULL, "shows this help",
314 0, &MONKEY_GETOPT_format_help_, "Monkey Pathologist: Automatically debug a service"},
315 {'i', "inspect", "EXPRESSIONNAME", "expression to inspect in the function specified after argument f",
316 1, &MONKEY_GETOPT_set_string, &inspectExpression},
317 {'l', "valgrind", "FILENAME", "path to valgrind binary. If not passed, pathologist will set it to /usr/bin/valgrind",
318 1, &MONKEY_GETOPT_set_string, &valgrindBinaryPath},
319 {'m', "mail", "MAILADDRESS", "if specified, pathologist will send the bugreport to the given address",
320 1, &MONKEY_GETOPT_set_string, &emailAddress},
321 {'o', "report", "FILENAME", "saves the xml formated report to the given file",
322 1, &MONKEY_GETOPT_set_string, &dumpFileName},
323 {'p', "depth", "UINT", "scope depth. How many scopes should pathologist lookup expression values outer than the scope in which the problem occurs. Default is 0 which means, pathologist is restricted to the scope of the expression in which the debugged program stopped" ,
324 1, &MONKEY_GETOPT_set_uint, &scopeDepth},
325 {'r', "reverse", NULL, "enables reverse execution",
326 0, &MONKEY_GETOPT_set_one, &reverseExecutionAllowed},
327 {'v', "version", NULL, "print the version number",
328 0, &MONKEY_GETOPT_print_version_, "0.1 alpha"},
329 MONKEY_GETOPT_OPTION_END
330 };
331
332 if (-1 == (ret = MONKEY_GETOPT_run ("pathologist -d DATABASEFILE [options] [--] BINARY", options, (unsigned int) argc, argv)))
333 return -1;
334
335 // Check for required arguments
336 if (argc <= ret)
337 printf("Error: missing argument: path to the binary file.\n");
338 if (NULL == edbFilePath)
339 printf("Error: missing argument: path to expression database file.\n");
340 if (argc <= ret || NULL == edbFilePath)
341 exit(EXIT_FAILURE);
342
343 /* All remaining args are considered program arguments */
344 binaryName = argv[ret];
345 command = (char *)buildBinaryArgs(argc - ret, &argv[ret]) + 1;
346 binaryArgs = (char *)buildBinaryArgs(argc - ret - 1, &argv[ret + 1]);
347
348 printf("\n%s\n%s\n%s\n\n", binaryName, command, binaryArgs);
349
350 /* Run Pathologist */
351 run();
352
353 /* clean up */
354 freePathologistArgs();
355
356 return ret;
357}
diff --git a/pathologist/src/pathologist/pathologist_edb.h b/pathologist/src/pathologist/pathologist_edb.h
new file mode 100644
index 0000000..33e18ee
--- /dev/null
+++ b/pathologist/src/pathologist/pathologist_edb.h
@@ -0,0 +1,158 @@
1/**
2 * @file monkey/MONKEY_edb.h
3 * @brief Monkey API for accessing the Expression Database (edb)
4 */
5
6#ifndef MONKEY_EDB_H
7#define MONKEY_EDB_H
8
9#ifdef __cplusplus
10extern "C"
11{
12#if 0 /* keep Emacsens' auto-indent happy */
13}
14#endif
15#endif
16
17
18struct MONKEY_EDB_Context;
19
20/**
21 * Establish a connection to the Expression Database
22 *
23 * @param db_file_name path the Expression Database file
24 * @return context to use for Accessing the Expression Database, NULL on error
25 */
26struct MONKEY_EDB_Context *MONKEY_EDB_connect (const char
27 *db_file_name);
28
29
30/**
31 * Disconnect from Database, and cleanup resources
32 *
33 * @param context context
34 * @return MONKEY_OK on success, MONKEY_NO on failure
35 */
36int MONKEY_EDB_disconnect (struct MONKEY_EDB_Context *cntxt);
37
38
39typedef int (*MONKEY_ExpressionIterator) (void *, int, char **,
40 char **);
41
42typedef int (*MONKEY_FileIterator) (void *, int, char **, char **);
43
44
45
46int
47MONKEY_EDB_get_all_outer_scopes(struct MONKEY_EDB_Context
48 *cntxt, const char *file_name,
49 int function_beginning,
50 int scope_in_question_start,
51 int scope_in_question_end,
52 MONKEY_ExpressionIterator
53 iter, void *iter_cls);
54
55int
56MONKEY_EDB_expression_function_end_scope(struct MONKEY_EDB_Context
57 *cntxt, const char *file_name,
58 int start_lineno,
59 MONKEY_ExpressionIterator
60 iter, void *iter_cls);
61int
62MONKEY_EDB_function_start_line_for_scope(struct MONKEY_EDB_Context
63 *cntxt, const char *file_name,
64 int scope_end,
65 MONKEY_ExpressionIterator
66 iter, void *iter_cls);
67/**
68 * Return the line number of the end-of-scope for the expression indicated by start_line_no
69 *
70 * @param cntxt context containing the Expression Database handle
71 * @param file_name path to the file in which the expression in question exists
72 * @param start_line_no expression's line
73 * @param iter callback function, iterator for values returned from the Database
74 * @param iter_cls closure for the expression iterator, will contain the scope-end line number
75 * @return MONKEY_OK on success, MONKEY_NO on failure
76 */
77int
78MONKEY_EDB_get_expression_scope_end (struct MONKEY_EDB_Context
79 *cntxt, const char *file_name,
80 int start_line_no,
81 MONKEY_ExpressionIterator
82 iter, void *iter_cls);
83
84
85int
86MONKEY_EDB_get_expression_scope_end_for_expression (struct MONKEY_EDB_Context
87 *cntxt, const char *file_name,
88 const char * expr_syntax,
89 MONKEY_ExpressionIterator
90 iter, void *iter_cls);
91
92/**
93 * Return all the source code file names available in the Expression Database
94 *
95 * @param cntxt context containing the Expression Database handle
96 * @param iter callback function, iterator for values returned from the Database
97 * @param iter_cls closure for the file names iterator, will contain the file names
98 * @return MONKEY_OK on success, MONKEY_NO on failure
99 */
100int
101MONKEY_EDB_get_file_names (struct MONKEY_EDB_Context *cntxt,
102 MONKEY_FileIterator iter,
103 void *iter_cls);
104
105
106int
107MONKEY_EDB_get_globals (struct MONKEY_EDB_Context *cntxt,
108 const char* file_names,
109 MONKEY_ExpressionIterator iter,
110 void *iter_cls);
111
112/**
113 * Run an SQLite query to retrieve those expressions that are previous to
114 * given expression and are in the same scope of the given expression
115 * For example, consider the following code snippet:
116 *
117 * {
118 * struct Something whole; // line no.1
119 * struct SomethingElse part; // line no.2
120 * whole.part = &part; // line no.3
121 * whole.part->member = 1; // line no.4
122 * }
123 *
124 * If the expression supplied to the function is that of line no.4 "whole.part->member = 1;"
125 * The returned list of expressions will be: whole.part (line no.4), whole.part->member (line no.4),
126 * whole (line no.3), whole.part (line no.3), &part (line no.3), whole.part = &part (line no.3)
127 *
128 * @param cntxt context containing the Expression Database handle.
129 * @param file_name path to the file in which the expression in question exists
130 * @param start_line_no expression beginning line
131 * @param iter callback function, iterator for expressions returned from the Database
132 * @param iter_cls closure for the expression iterator
133 * @return MONKEY_OK success, MONKEY_NO failure
134 */
135int
136MONKEY_EDB_get_expressions (struct MONKEY_EDB_Context *cntxt,
137 const char *file_name, int start_line_no,
138 MONKEY_ExpressionIterator iter,
139 void *iter_cls);
140
141
142int
143MONKEY_EDB_get_sub_expressions (struct MONKEY_EDB_Context
144 *cntxt, const char *file_name,
145 int start_line_no, int end_line_no,
146 MONKEY_ExpressionIterator iter,
147 void *iter_cls);
148
149
150
151#if 0 /* keep Emacsens' auto-indent happy */
152{
153#endif
154#ifdef __cplusplus
155}
156#endif
157
158#endif
diff --git a/pathologist/src/pathologist/pathologist_xml_writer.h b/pathologist/src/pathologist/pathologist_xml_writer.h
new file mode 100644
index 0000000..5e74060
--- /dev/null
+++ b/pathologist/src/pathologist/pathologist_xml_writer.h
@@ -0,0 +1,54 @@
1/**
2 * @file monkey/MONKEY_xml_writer.h
3 * @brief Monkey API for generating XML debug report
4 */
5
6
7#ifndef MONKEY_XML_WRITER_H
8#define MONKEY_XML_WRITER_H
9
10#ifdef __cplusplus
11extern "C"
12{
13#if 0 /* keep Emacsens' auto-indent happy */
14}
15#endif
16#endif
17
18
19struct XmlAttribute {
20 struct XmlAttribute *next;
21 struct XmlAttribute *prev;
22 const char *name;
23 const char *value;
24};
25
26
27struct MONKEY_XML_Node {
28 struct MONKEY_XML_Node *next;
29 struct MONKEY_XML_Node *prev;
30 const char *name;
31 const char *value;
32 const char *innerText;
33 struct XmlAttribute* attributeListHead;
34 struct XmlAttribute* attributeListTail;
35 struct MONKEY_XML_Node *childrenListHead;
36 struct MONKEY_XML_Node *childrenListTail;
37};
38
39struct MONKEY_XML_Node* MONKEY_XML_WRITER_new_node(const char *name, const char *innerText);
40int MONKEY_XML_WRITER_delete_tree(struct MONKEY_XML_Node *root);
41struct MONKEY_XML_Node* MONKEY_XML_WRITER_add_child(struct MONKEY_XML_Node *parent, struct MONKEY_XML_Node *child);
42int MONKEY_XML_WRITER_write_document(FILE* file, struct MONKEY_XML_Node *root);
43FILE* MONKEY_XML_WRITER_create_document(const char *filePath);
44int MONKEY_XML_WRITER_add_attribute(struct MONKEY_XML_Node* node, const char *attrName, const char *attrValue);
45int MONKEY_XML_WRITER_add_inner_text(struct MONKEY_XML_Node *node, const char *innerText);
46
47#if 0 /* keep Emacsens' auto-indent happy */
48{
49#endif
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/pathologist/src/pathologist/test_monkey_assertion_failure.sh b/pathologist/src/pathologist/test_monkey_assertion_failure.sh
new file mode 100644
index 0000000..2a6d3b0
--- /dev/null
+++ b/pathologist/src/pathologist/test_monkey_assertion_failure.sh
@@ -0,0 +1,16 @@
1#!/bin/sh
2echo -n "Test Monkey with Bug - Assertion Failure -"
3gnunet-monkey -m text -d bug_assertion_failure.db -b bug_assertion_failure -o monkey.out || (echo "Monkey Failed!" && exit 1)
4grep "Bug detected in file:bug_assertion_failure.c" monkey.out > /dev/null || (echo "FAIL" && exit 1)
5grep "function:assertionFailure" monkey.out > /dev/null || (echo "FAIL" && exit 1)
6grep "line:8" monkey.out > /dev/null || (echo "FAIL" && exit 1)
7grep "received signal:SIGABRT" monkey.out > /dev/null || (echo "FAIL" && exit 1)
8grep "Aborted" monkey.out > /dev/null || (echo "FAIL" && exit 1)
9grep "Details:" monkey.out > /dev/null || (echo "FAIL" && exit 1)
10grep "Assertion Failure" monkey.out > /dev/null || (echo "FAIL" && exit 1)
11grep "Expression evaluation:" monkey.out > /dev/null || (echo "FAIL" && exit 1)
12grep "assert(x<4) = Not evaluated" monkey.out > /dev/null || (echo "FAIL" && exit 1)
13grep "x<4 = 0" monkey.out > /dev/null || (echo "FAIL" && exit 1)
14grep "x = 5" monkey.out > /dev/null || (echo "FAIL" && exit 1)
15rm -f monkey.out
16echo "PASS"
diff --git a/pathologist/src/pathologist/test_monkey_bad_memory_access.sh b/pathologist/src/pathologist/test_monkey_bad_memory_access.sh
new file mode 100644
index 0000000..cd86a84
--- /dev/null
+++ b/pathologist/src/pathologist/test_monkey_bad_memory_access.sh
@@ -0,0 +1,15 @@
1echo -n "Test Monkey with Bug - Bad Memory Access -"
2gnunet-monkey -m text -d bug_bad_memory_access.db -b bug_bad_memory_access -o monkey.out || (echo "Monkey Failed!" && exit 1)
3for i in `cat bug_bad_memory_access_rpt.ref`
4do
5 grep $i monkey.out
6 if [ $? -ne 0 ]
7 then
8 {
9 echo $i
10 echo "FAIL"
11 exit 1
12 }
13 fi
14done
15echo "PASS"
diff --git a/pathologist/src/pathologist/test_monkey_data.conf b/pathologist/src/pathologist/test_monkey_data.conf
new file mode 100644
index 0000000..9ae1d67
--- /dev/null
+++ b/pathologist/src/pathologist/test_monkey_data.conf
@@ -0,0 +1,43 @@
1[PATHS]
2SERVICEHOME = /tmp/test-gnunetd-arm/
3DEFAULTCONFIG = test_arm_api_data.conf
4
5[arm]
6PORT = 23354
7DEFAULTSERVICES =
8BINARY = gnunet-service-arm
9OPTIONS = -L ERROR
10# DEBUG = YES
11#PREFIX = valgrind --tool=memcheck --leak-check=yes
12
13[gnunet-monkey]
14# DEBUG = YES
15PORT = 23355
16BINARY = gnunet-monkey
17# PREFIX = valgrind
18
19
20[fs]
21AUTOSTART = NO
22
23[datastore]
24AUTOSTART = NO
25
26[core]
27AUTOSTART = NO
28
29[transport]
30AUTOSTART = NO
31
32[peerinfo]
33AUTOSTART = NO
34
35[statistics]
36AUTOSTART = YES
37# DEBUG = NO
38
39
40[dns]
41AUTOSTART = NO
42
43
diff --git a/pathologist/src/pathologist/test_monkey_npe.sh b/pathologist/src/pathologist/test_monkey_npe.sh
new file mode 100755
index 0000000..5f3d528
--- /dev/null
+++ b/pathologist/src/pathologist/test_monkey_npe.sh
@@ -0,0 +1,13 @@
1#!/bin/sh
2echo -n "Test Monkey with Bug - Null Pointer Exception -"
3gnunet-monkey -m text -d bug_null_pointer_exception.db -b bug_null_pointer_exception -o npe.out || (echo "Monkey Failed!" && exit 1)
4grep "Bug detected in file:bug_null_pointer_exception.c" npe.out > /dev/null || (echo "FAIL" && exit 1)
5grep "function:crashFunction" npe.out > /dev/null || (echo "FAIL" && exit 1)
6grep "line:14" npe.out > /dev/null || (echo "FAIL" && exit 1)
7grep "reason:(null)" npe.out > /dev/null || (echo "FAIL" && exit 1)
8grep "received signal:SIGSEGV" npe.out > /dev/null || (echo "FAIL" && exit 1)
9grep "Segmentation fault" npe.out > /dev/null || (echo "FAIL" && exit 1)
10grep " Details:" npe.out > /dev/null || (echo "FAIL" && exit 1)
11grep " Expression:crashStruct is NULL" npe.out > /dev/null || (echo "FAIL" && exit 1)
12rm -f npe.out
13echo "PASS"
diff --git a/pathologist/src/pathologist/test_pathologist.c b/pathologist/src/pathologist/test_pathologist.c
new file mode 100644
index 0000000..eac5d2f
--- /dev/null
+++ b/pathologist/src/pathologist/test_pathologist.c
@@ -0,0 +1,412 @@
1#define _GNU_SOURCE
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include "mxml.h"
6
7#undef DEBUG_ENABLED
8static int OK = 0;
9static int NO = 1;
10static char *reportPath = "../../refs/reports";
11static char *dbPath = "../../refs/db";
12static char *binPath = "../../refs/src";
13
14int compareReports(const char *refFileName, const char *testFileName) {
15 FILE *testFilePtr;
16 FILE *refFilePtr;
17 mxml_node_t *refTree;
18 mxml_node_t *testTree;
19 mxml_node_t *refNode;
20 mxml_node_t *testNode;
21 mxml_node_t *refEpochNode;
22 mxml_node_t *testEpochNode;
23 mxml_node_t *refFunctionNode;
24 mxml_node_t *testFunctionNode;
25 mxml_node_t *refExpressionNode;
26 mxml_node_t *testExpressionNode;
27 const char *refExpressionValue;
28 const char *testExpressionValue;
29
30 refFilePtr = fopen(refFileName, "r");
31 testFilePtr = fopen(testFileName, "r");
32 if (NULL == refFilePtr) {
33 fprintf(stderr, "Test failed: cannot locate reference report: %s.\n", strerror(errno));
34 return NO;
35 }
36 if (NULL == testFilePtr) {
37 fprintf(stderr, "Test failed: cannot locate test report: %s.\n", strerror(errno));
38 return NO;
39 }
40
41 refTree = mxmlLoadFile(NULL, refFilePtr, MXML_TEXT_CALLBACK);
42 testTree = mxmlLoadFile(NULL, testFilePtr, MXML_TEXT_CALLBACK);
43 if (NULL == refTree) {
44 fprintf(stderr, "Test failed: cannot parse reference report.\n");
45 return NO;
46 }
47 if (NULL == testTree) {
48 fprintf(stderr, "Test failed: cannot parse test report.\n");
49 return NO;
50 }
51 fclose(refFilePtr);
52 fclose(testFilePtr);
53
54 refNode = refTree; testNode = testTree; // <?xml version="1.0"?>
55
56 // <crash>...
57 refNode = mxmlWalkNext(mxmlGetFirstChild(refNode), refTree, MXML_DESCEND);
58 testNode = mxmlWalkNext(mxmlGetFirstChild(testNode), testTree, MXML_DESCEND);
59 if (0 != strcmp(mxmlGetElement(refNode), "crash") ||
60 0 != strcmp(mxmlGetElement(testNode), "crash")) {
61 fprintf(stderr, "Test failed: wrong tag. <crash> expected\n");
62 return NO;
63 }
64 if (0 != strcmp(mxmlElementGetAttr(refNode, "category"), mxmlElementGetAttr(testNode, "category")) ||
65 0 != strcmp(mxmlElementGetAttr(refNode, "function"), mxmlElementGetAttr(testNode, "function")) ||
66 0 != strcmp(mxmlElementGetAttr(refNode, "line"), mxmlElementGetAttr(testNode, "line")) ||
67 0 != strcmp(mxmlElementGetAttr(refNode, "file"), mxmlElementGetAttr(testNode, "file"))) {
68 fprintf(stderr, "Test failed: crash attributes mismatch.\n");
69 return NO;
70 }
71
72 // <valgrind> or <history>...
73 refNode = mxmlWalkNext(mxmlGetFirstChild(refNode), refTree, MXML_DESCEND);
74 testNode = mxmlWalkNext(mxmlGetFirstChild(testNode), testTree, MXML_DESCEND);
75 if (0 == strcmp(mxmlGetElement(refNode), "valgrind")) {
76 if (0 != strcmp(mxmlGetElement(testNode), "valgrind")) {
77 fprintf(stderr, "Test failed: wrong tag, <valgrind> expected.\n");
78 return NO;
79 }
80 refNode = mxmlFindElement(refNode, refTree, "history", NULL, NULL, MXML_DESCEND); // move to <history>
81 testNode = mxmlFindElement(testNode, testTree, "history", NULL, NULL, MXML_DESCEND);
82 } else if (0 == strcmp(mxmlGetElement(refNode), "history")) {
83 if (0 != strcmp(mxmlGetElement(testNode), "history")) {
84 fprintf(stderr, "Test failed: wrong tag, <history> expected.\n");
85 return NO;
86 }
87 } else {
88 fprintf(stderr, "Test failed: unknown tag.\n");
89 return NO;
90 }
91
92 // <epoch>'s
93 refEpochNode = mxmlGetFirstChild(refNode);
94 testEpochNode = mxmlGetFirstChild(testNode);
95 while (NULL != refEpochNode && NULL != testEpochNode) {
96 if (0 != strcmp(mxmlGetElement(refEpochNode), "epoch") ||
97 0 != strcmp(mxmlGetElement(testEpochNode), "epoch")) {
98 fprintf(stderr, "Test failed: wrong tag, <epoch> expected.\n");
99 return NO;
100 }
101 // Comparing the epoch steps
102 if (0 != strcmp(mxmlElementGetAttr(refEpochNode, "step"), mxmlElementGetAttr(testEpochNode, "step"))) {
103 fprintf(stderr, "Test failed: epoch steps mismatch.\n");
104 return NO;
105 }
106
107 // <trace>
108 refNode = mxmlWalkNext(mxmlGetFirstChild(refEpochNode), refTree, MXML_DESCEND);
109 testNode = mxmlWalkNext(mxmlGetFirstChild(testEpochNode), testTree, MXML_DESCEND);
110
111 // <function>'s
112 refFunctionNode = mxmlGetFirstChild(refNode);
113 testFunctionNode = mxmlGetFirstChild(testNode);
114 while (NULL != refFunctionNode && NULL != testFunctionNode) {
115 if (0 != strcmp(mxmlGetElement(refFunctionNode), "function") ||
116 0 != strcmp(mxmlGetElement(testFunctionNode), "function")) {
117 fprintf(stderr, "Test failed: wrong tag, <function> expected.\n");
118 return NO;
119 }
120 //comparing function attributes
121 if (0 != strcmp(mxmlElementGetAttr(refFunctionNode, "name"), mxmlElementGetAttr(testFunctionNode, "name")) ||
122 0 != strcmp(mxmlElementGetAttr(refFunctionNode, "line"), mxmlElementGetAttr(testFunctionNode, "line")) ||
123 0 != strcmp(mxmlElementGetAttr(refFunctionNode, "file"), mxmlElementGetAttr(testFunctionNode, "file")) ||
124 0 != strcmp(mxmlElementGetAttr(refFunctionNode, "depth"), mxmlElementGetAttr(testFunctionNode, "depth"))) {
125 fprintf(stderr, "Test failed: function attributes mismatch.\n");
126 return NO;
127 }
128
129 // <expressions>
130 refNode = mxmlWalkNext(mxmlGetFirstChild(refFunctionNode), refTree, MXML_DESCEND);
131 testNode = mxmlWalkNext(mxmlGetFirstChild(testFunctionNode), testTree, MXML_DESCEND);
132
133 // <expression>'s
134 refExpressionNode = mxmlGetFirstChild(refNode);
135 testExpressionNode = mxmlGetFirstChild(testNode);
136 while (NULL != refExpressionNode && NULL != testExpressionNode) {
137 if (0 != strcmp(mxmlGetElement(refExpressionNode), "expression") ||
138 0 != strcmp(mxmlGetElement(testExpressionNode), "expression")) {
139 fprintf(stderr, "Test failed: wrong tag, <expression> expected.\n");
140 return NO;
141 }
142
143 // comparing expression syntax
144 if (0 != strcmp(mxmlElementGetAttr(refExpressionNode, "name"), mxmlElementGetAttr(testExpressionNode, "name"))) {
145 fprintf(stderr, "Test failed: expression syntax mismatch.\n");
146 return NO;
147 }
148
149 // comparing expression values
150 refExpressionValue = mxmlGetText(refExpressionNode, 0);
151 testExpressionValue = mxmlGetText(testExpressionNode, 0);
152 if (0 != strcmp(refExpressionValue, testExpressionValue)) {
153 // different pointer values are accepted
154 if (!(refExpressionValue[0] == '0' && refExpressionValue[1] == 'x'
155 && testExpressionValue[0] == '0' && testExpressionValue[1] == 'x')) {
156 if ((strlen(refExpressionValue) >= 5) || (strlen(testExpressionValue) >= 5)) {
157 // different numeric values longer than 5 digits are accepted (such values are considered garbage in uninitialized variables)
158 char *endPtr = NULL;
159 long refIntVal;
160 long testIntVal;
161 refIntVal = strtol(refExpressionValue, &endPtr, 0); // testing whether the values are numeric
162 testIntVal = strtol(testExpressionValue, &endPtr, 0);
163 if ((0 == refIntVal || 0 == testIntVal) && (ERANGE == errno || EINVAL == errno)) {
164 fprintf(stderr, "Test failed: expression value mismatch.\n");
165 return NO;
166 }
167 } else {
168 // not pointers and not 5+ digits numbers, then mismatch
169 fprintf(stderr, "Test failed: expression value mismatch.\n");
170 return NO;
171 }
172 }
173 }
174
175 // next expression
176 refExpressionNode = mxmlGetNextSibling(mxmlGetNextSibling(refExpressionNode));
177 testExpressionNode = mxmlGetNextSibling(mxmlGetNextSibling(testExpressionNode));
178 }
179 if (NULL != refExpressionNode || NULL != testExpressionNode) {
180 fprintf(stderr, "Test failed: expression mismatch.\n");
181 return NO;
182 }
183
184 // next function
185 refFunctionNode = mxmlGetNextSibling(mxmlGetNextSibling(refFunctionNode));
186 testFunctionNode = mxmlGetNextSibling(mxmlGetNextSibling(testFunctionNode));
187 }
188 if (NULL != refFunctionNode || NULL != testFunctionNode) {
189 fprintf(stderr, "Test failed: function mismatch.\n");
190 return NO;
191 }
192
193 // next epoch step
194 refEpochNode = mxmlGetNextSibling(mxmlGetNextSibling(refEpochNode));
195 testEpochNode = mxmlGetNextSibling(mxmlGetNextSibling(testEpochNode));
196 }
197 if (NULL != refEpochNode || NULL != testEpochNode) {
198 fprintf(stderr, "Test failed: epoch steps mismatch.\n");
199 return NO;
200 }
201
202 mxmlDelete(refTree);
203 mxmlDelete(testTree);
204 return OK;
205}
206
207
208int runTest(const char *refReportName, const char *testReportName,
209 const char *dbName, const char *binaryName, char *commandStr) {
210 FILE *pathologistPipe;
211 char *refReportPath;
212 char *testReportPath;
213 char *dbFilePath;
214 char *binFilePath;
215 char *command;
216 int ret = OK;
217
218 asprintf(&testReportPath, "%s/%s", reportPath, testReportName);
219 asprintf(&dbFilePath, "%s/%s", dbPath, dbName);
220 asprintf(&binFilePath, "%s/%s", binPath, binaryName);
221 asprintf(&command, commandStr, dbFilePath, testReportPath, binFilePath);
222 asprintf(&refReportPath, "%s/%s", reportPath, refReportName);
223
224 // run Monkey pathologist
225 pathologistPipe = popen(command, "r");
226#ifdef DEBUG_ENABLED
227 fprintf(stderr, "Running command: %s\n", command);
228#endif
229 if (NULL == pathologistPipe) {
230 fprintf(stderr, "Fatal error: unable to run Monkey pathologist.\n");
231 ret = NO;
232 }
233 else {
234 char buffer[128];
235 while(!feof(pathologistPipe)) {
236 if(fgets(buffer, 128, pathologistPipe) != NULL) {
237#ifdef DEBUG_ENABLED
238 fputs(buffer, stdout);
239#endif
240 }
241 }
242 pclose(pathologistPipe);
243 // compare results with ref
244 if (NO == compareReports(refReportPath, testReportPath)) {
245 ret = NO;
246 } else {
247 // test passed, delete test report
248 if (0 != remove(testReportPath)) {
249 fprintf(stderr, "Warning: could not remove test file %s\n", testReportPath);
250 }
251 }
252 }
253
254 free(refReportPath); free(command); free(binFilePath); free(dbFilePath); free(testReportPath);
255 return ret;
256}
257
258int main() {
259 int ret = OK;
260 char *commandStr = "pathologist -d %s -o %s %s";
261 char *commandStrReverse = "pathologist -d %s -o %s -r %s";
262 char *commandStrDepthOne = "pathologist -d %s -o %s -p 1 %s";
263 char *commandStrDepthOneReverse = "pathologist -d %s -o %s -p 1 -r %s";
264 char *commandStrDepthThousand = "pathologist -d %s -o %s -p 1000 %s";
265
266 fprintf(stderr, "Testing Monkey Pathologist...\n");
267
268 // Bug Null Pointer Exception
269 fprintf(stderr, "Testing bug null pointer exception...\n");
270 if (NO == runTest("ref_bug_null_pointer_exception.xml",
271 "test_bug_null_pointer_exception.xml", "bug_null_pointer_exception.db",
272 "bug_null_pointer_exception", commandStr)) {
273 ret = NO;
274 fprintf(stderr, "Test bug null pointer exception: FAILED\n");
275 } else {
276 fprintf(stderr, "Test bug null pointer exception: PASSED\n");
277 }
278
279 // Bug Null Pointer Exception with backtracking
280 fprintf(stderr, "Testing bug null pointer exception with backtracking...\n");
281 if (NO == runTest("ref_bt_bug_null_pointer_exception.xml",
282 "test_bt_bug_null_pointer_exception.xml", "bug_null_pointer_exception.db",
283 "bug_null_pointer_exception", commandStrReverse)) {
284 ret = NO;
285 fprintf(stderr, "Test bug null pointer exception with backtracking: FAILED\n");
286 } else {
287 fprintf(stderr, "Test bug null pointer exception with backtracking: PASSED\n");
288 }
289
290 // Bug Null Pointer Exception modified with backtracking
291 fprintf(stderr, "Testing bug null pointer exception modified with backtracking...\n");
292 if (NO == runTest("ref_bt_bug_null_pointer_exception_modified.xml",
293 "test_bt_bug_null_pointer_exception_modified.xml", "bug_null_pointer_exception_modified.db",
294 "bug_null_pointer_exception_modified", commandStrReverse)) {
295 ret = NO;
296 fprintf(stderr, "Test bug null pointer exception modified with backtracking: FAILED\n");
297 } else {
298 fprintf(stderr, "Test bug null pointer exception modified with backtracking: PASSED\n");
299 }
300
301 // Bug Bad Memory Access
302 fprintf(stderr, "Testing bug bad memory access...\n");
303 if (NO == runTest("ref_bug_bad_memory_access.xml",
304 "test_bug_bad_memory_access.xml", "bug_bad_memory_access.db",
305 "bug_bad_memory_access", commandStr)) {
306 ret = NO;
307 fprintf(stderr, "Test bug bad memory access: FAILED\n");
308 } else {
309 fprintf(stderr, "Test bug bad memory access: PASSED\n");
310 }
311
312 // Bug Bad Memory Access with backtracking
313 fprintf(stderr, "Testing bug bad memory access with backtracking...\n");
314 if (NO == runTest("ref_bt_bug_bad_memory_access.xml",
315 "test_bt_bug_bad_memory_access.xml", "bug_bad_memory_access.db",
316 "bug_bad_memory_access", commandStrReverse)) {
317 ret = NO;
318 fprintf(stderr, "Test bug bad memory access with backtracking: FAILED\n");
319 } else {
320 fprintf(stderr, "Test bug bad memory access with backtracking: PASSED\n");
321 }
322
323 // Bug Assertion Failure
324 fprintf(stderr, "Testing bug assertion failure...\n");
325 if (NO == runTest("ref_bug_assertion_failure.xml",
326 "test_bug_assertion_failure.xml", "bug_assertion_failure.db",
327 "bug_assertion_failure", commandStr)) {
328 ret = NO;
329 fprintf(stderr, "Test bug assertion failure: FAILED\n");
330 } else {
331 fprintf(stderr, "Test bug assertion failure: PASSED\n");
332 }
333
334 // Bug Assertion Failure with backtracking
335 fprintf(stderr, "Testing bug assertion failure with backtracking...\n");
336 if (NO == runTest("ref_bt_bug_assertion_failure.xml",
337 "test_bt_bug_assertion_failure.xml", "bug_assertion_failure.db",
338 "bug_assertion_failure", commandStrReverse)) {
339 ret = NO;
340 fprintf(stderr, "Test bug assertion failure with backtracking: FAILED\n");
341 } else {
342 fprintf(stderr, "Test bug assertion failure with backtracking: PASSED\n");
343 }
344
345 // Bug Division By Zero Loop no depth
346 fprintf(stderr, "Testing bug division by zero loop no depth...\n");
347 if (NO == runTest("ref_bug_division_by_zero_nodepth.xml",
348 "test_bug_division_by_zero_nodepth.xml", "bug_division_by_zero_loop.db",
349 "bug_division_by_zero_loop", commandStr)) {
350 ret = NO;
351 fprintf(stderr, "Test bug division by zero loop with no depth: FAILED\n");
352 } else {
353 fprintf(stderr, "Test bug division by zero loop with no depth: PASSED\n");
354 }
355
356 // Bug Division By Zero Loop no depth with backtracking
357 fprintf(stderr, "Testing bug division by zero loop no depth with backtracking...\n");
358 if (NO == runTest("ref_bt_bug_division_by_zero_nodepth.xml",
359 "test_bt_bug_division_by_zero_nodepth.xml", "bug_division_by_zero_loop.db",
360 "bug_division_by_zero_loop", commandStrReverse)) {
361 ret = NO;
362 fprintf(stderr, "Test bug division by zero loop with no depth with backtracking: FAILED\n");
363 } else {
364 fprintf(stderr, "Test bug division by zero loop with no depth with backtracking: PASSED\n");
365 }
366
367 // Bug Division By Zero Loop depth 1
368 fprintf(stderr, "Testing bug division by zero loop depth 1...\n");
369 if (NO == runTest("ref_bug_division_by_zero_depth_1.xml",
370 "test_bug_division_by_zero_depth_1.xml", "bug_division_by_zero_loop.db",
371 "bug_division_by_zero_loop", commandStrDepthOne)) {
372 ret = NO;
373 fprintf(stderr, "Test bug division by zero loop with depth 1: FAILED\n");
374 } else {
375 fprintf(stderr, "Test bug division by zero loop with depth 1: PASSED\n");
376 }
377
378 // Bug Division By Zero Loop depth 1 with backtracking
379 fprintf(stderr, "Testing bug division by zero loop depth 1 with backtracking...\n");
380 if (NO == runTest("ref_bt_bug_division_by_zero_depth_1.xml",
381 "test_bt_bug_division_by_zero_depth_1.xml", "bug_division_by_zero_loop.db",
382 "bug_division_by_zero_loop", commandStrDepthOneReverse)) {
383 ret = NO;
384 fprintf(stderr, "Test bug division by zero loop with depth 1 with backtracking: FAILED\n");
385 } else {
386 fprintf(stderr, "Test bug division by zero loop with depth 1 with backtracking: PASSED\n");
387 }
388
389 // Bug Division By Zero Loop depth 1000
390 fprintf(stderr, "Testing bug division by zero loop depth 1000...\n");
391 if (NO == runTest("ref_bug_division_by_zero_depth_1.xml",
392 "test_bug_division_by_zero_depth_1000.xml", "bug_division_by_zero_loop.db",
393 "bug_division_by_zero_loop", commandStrDepthThousand)) {
394 ret = NO;
395 fprintf(stderr, "Test bug division by zero loop with depth 1000: FAILED\n");
396 } else {
397 fprintf(stderr, "Test bug division by zero loop with depth 1000: PASSED\n");
398 }
399
400 // Bug Bad Food
401 fprintf(stderr, "Testing bug bad food...\n");
402 if (NO == runTest("ref_bug_bad_food.xml",
403 "test_bug_bad_food.xml", "bug_bad_food.db",
404 "bug_bad_food", commandStr)) {
405 ret = NO;
406 fprintf(stderr, "Test bug bad food: FAILED\n");
407 } else {
408 fprintf(stderr, "Test bug bad food: PASSED\n");
409 }
410
411 return ret;
412}
diff --git a/pathologist/src/pathologist/xml_writer.c b/pathologist/src/pathologist/xml_writer.c
new file mode 100644
index 0000000..64775a4
--- /dev/null
+++ b/pathologist/src/pathologist/xml_writer.c
@@ -0,0 +1,126 @@
1/**
2 * @file monkey/xml_writer.c
3 * @brief Monkey API for generating XML debug report
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <assert.h>
9#include <string.h>
10#include "monkey_common.h"
11#include "pathologist_xml_writer.h"
12
13
14struct MONKEY_XML_Node* MONKEY_XML_WRITER_new_node(const char *name, const char *innerText) {
15 struct MONKEY_XML_Node *node = MONKEY_malloc(sizeof(struct MONKEY_XML_Node));
16 node->name = name;
17 node->innerText = innerText;
18 node->childrenListHead = NULL;
19 node->childrenListTail = NULL;
20 node->attributeListHead = NULL;
21 node->attributeListTail = NULL;
22 return node;
23}
24
25
26int MONKEY_XML_WRITER_add_attribute(struct MONKEY_XML_Node* node, const char *attrName, const char *attrValue)
27{
28 struct XmlAttribute *attribute = MONKEY_malloc(sizeof(struct XmlAttribute));
29 attribute->name = attrName;
30 attribute->value = attrValue;
31 attribute->next = NULL; attribute->prev = NULL;
32 MONKEY_CONTAINER_DLL_insert_tail (node->attributeListHead, node->attributeListTail,
33 attribute);
34 return MONKEY_OK;
35}
36
37
38int MONKEY_XML_WRITER_add_inner_text(struct MONKEY_XML_Node *node, const char *innerText)
39{
40 node->innerText = innerText;
41 return MONKEY_OK;
42}
43
44
45int MONKEY_XML_WRITER_delete_tree(struct MONKEY_XML_Node *root)
46{
47 struct MONKEY_XML_Node *tmp = NULL;
48 struct XmlAttribute *tmpAttribute = NULL;
49
50 /* MONKEY_freeing children list - Depth First */
51 while (NULL != root->childrenListHead) {
52 tmp = root->childrenListHead;
53 root->childrenListHead = tmp->next;
54 MONKEY_XML_WRITER_delete_tree(tmp);
55 }
56
57 /* MONKEY_freeing Attributes List */
58 while (NULL != root->attributeListHead) {
59 tmpAttribute = root->attributeListHead;
60 root->attributeListHead = tmpAttribute->next;
61 MONKEY_free(tmpAttribute);
62 }
63
64 /* MONKEY_freeing Leaf Node */
65 MONKEY_free(root);
66
67 return MONKEY_OK;
68}
69
70
71struct MONKEY_XML_Node* MONKEY_XML_WRITER_add_child(struct MONKEY_XML_Node *parent, struct MONKEY_XML_Node *child) {
72 child->next = NULL; child->prev = NULL;
73 MONKEY_CONTAINER_DLL_insert_tail (parent->childrenListHead, parent->childrenListTail,
74 child);
75 return child;
76}
77
78
79FILE* MONKEY_XML_WRITER_create_document(const char *filePath) {
80 FILE* file = fopen(filePath, "w");
81 if (NULL != file) {
82 fprintf(file, "<?xml version=\"1.0\"?>\n");
83 return file;
84 }
85 return NULL;
86}
87
88static char* escapeSpecialCharacters(const char * s) {
89 char* escaped;
90 escaped = MONKEY_str_replace_all (s, "&", "&amp;"); // & (escaping amp character MUST be the first, otherwise, it will spoil the other escaped characters
91 escaped = MONKEY_str_replace_all (escaped, "\"", "&quot;"); // single quote
92 escaped = MONKEY_str_replace_all (escaped, "'", "&apos;"); // double quotes
93 escaped = MONKEY_str_replace_all (escaped, "<", "&lt;"); // less than
94 escaped = MONKEY_str_replace_all (escaped, ">", "&gt;");// greater than
95
96 return escaped;
97}
98
99int MONKEY_XML_WRITER_write_document(FILE* file, struct MONKEY_XML_Node *root) {
100 struct MONKEY_XML_Node *tmp = root->childrenListHead;
101 struct XmlAttribute *tmpAttribute = root->attributeListHead;
102 if (!tmpAttribute)
103 fprintf(file, "<%s>", root->name);
104 else {
105 fprintf(file, "<%s ", root->name);
106 while (NULL != tmpAttribute) {
107 /* Escaping special characters in attribute values */
108 fprintf(file, "%s=\"%s\" ", tmpAttribute->name,
109 (tmpAttribute->value) ?
110 (escapeSpecialCharacters(tmpAttribute->value)) : "");
111 tmpAttribute = tmpAttribute->next;
112 }
113 fprintf(file, ">");
114 }
115 if(tmp) fprintf(file, "\n");
116
117 if (NULL != root->innerText)
118 fprintf(file, "%s", escapeSpecialCharacters(root->innerText));
119
120 while (NULL != tmp) {
121 MONKEY_XML_WRITER_write_document(file, tmp);
122 tmp = tmp->next;
123 }
124 fprintf(file, "</%s>\n", root->name);//End
125 return MONKEY_OK;
126}
diff --git a/pathologist/src/struct_parse/exmpl.c b/pathologist/src/struct_parse/exmpl.c
new file mode 100644
index 0000000..00d3a6f
--- /dev/null
+++ b/pathologist/src/struct_parse/exmpl.c
@@ -0,0 +1,31 @@
1#include <stdio.h>
2#include <stdlib.h>
3
4struct a {
5 char c;
6 char c2;
7 char* s[2];
8 struct a* a;
9 char r[4];
10 int i[2];
11 float f;
12};
13
14int main(int argc, char* argv[]) {
15 struct a a;
16 struct a b;
17 a.c = '\'';
18 a.c2 = '"';
19 a.s[0] = "bliblablu\"";
20 a.s[1] = "trololo";
21 a.a = &b;
22 a.r[0] = '\n';
23 a.r[1] = 'a';
24 a.r[2] = '';
25 a.r[3] = '"';
26 a.i[0] = -5;
27 a.i[1] = 42;
28 a.f = 3.141f;
29
30 return 0;
31}
diff --git a/pathologist/src/struct_parse/p.c b/pathologist/src/struct_parse/p.c
new file mode 100644
index 0000000..c99a654
--- /dev/null
+++ b/pathologist/src/struct_parse/p.c
@@ -0,0 +1,147 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5char* parse(char* str, int indent);
6
7// parses one pair of curly braces recursively.
8// expects first char to be the opening '{'
9// returns pointer to the next char after the closing '}' or NULL on error
10char* parse(char* str, int indent) {
11 int is_struct = 0, is_array = 0, had_equals = 0, had_children = 0, had_end = 0;
12 char* first = NULL;
13 char* second = NULL;
14 char* ws = NULL;
15 char* count = NULL;
16
17 if(*str++ != '{') return NULL;
18 while(*str == ' ') str++;
19 if(!*str) return NULL;
20 while(*str) {
21 first = str;
22 second = NULL;
23 had_equals = 0;
24 had_children = 0;
25 had_end = 0;
26 count = NULL;
27 while(*str) {
28 if(*str == '{') {
29 if( (is_struct && !had_equals) ||
30 (str != first && str != second) ) return NULL;
31 if(str == second) {
32 printf("%*s<expression name=\"%s\">\n", 2*indent, "", first);
33 had_children = 1;
34 }
35 str = parse(str, indent+1);
36 //continue; // have to check this char => no str++ at end of loop.
37 } else if(*str == '=') {
38 if(had_equals || is_array) return NULL;
39 had_equals = 1;
40 if(!is_struct && !is_array)
41 is_struct = 1;
42 for(ws = str-1; *ws == ' '; ws--)
43 *ws = '\0';
44 *str = '\0';
45 while(*++str == ' ');
46 second = str;
47 continue; // have to check this char => no str++ at end of loop.
48 } else if(*str == '\'' || *str == '"') {
49 char end_char = *str;
50 if(had_equals) second = str;
51 else first = str;
52 for(str++; *str != end_char; str++) {
53 if(!*str) return NULL;
54 if(*str == '\\') {
55 if(!*(str+1)) return NULL;
56 else str++;
57 }
58 }
59 } else if(*str == '<') {
60 for(ws = str-1; *ws == ' '; ws--)
61 *ws = '\0';
62 if(!(str = strpbrk(str+1, "0123456789>"))) return NULL;
63 if(*str == '>') continue;
64 count = str;
65 if(!(str = strpbrk(str+1, " >"))) return NULL;
66 if(*str == ' ')
67 *str = '\0';
68 else {
69 *str = '\0';
70 if(!(str = strchr(str+1, '>'))) return NULL;
71 }
72 } else if(*str == ',') {
73 if(is_struct && !had_equals) return NULL;
74 is_array = !is_struct;
75 is_struct = !is_array;
76 break;
77 } else if(*str == '}') {
78 had_end = 1;
79 break;
80 }
81 str++;
82 }
83 for(ws = str-1; *ws == ' '; ws--)
84 *ws = '\0';
85 *str = '\0';
86 if(had_children)
87 printf("%*s</expression>\n", 2*indent, "");
88 else if(is_array)
89 if(count)
90 printf("%*s<element count=\"%s\">%s</element>\n", 2*indent, "", count, first);
91 else
92 printf("%*s<element>%s</element>\n", 2*indent, "", first);
93 else
94 printf("%*s<expression name=\"%s\">%s</expression>\n", 2*indent, "", first, second);
95 if(had_end) return str;
96 str++;
97 while(*str == ' ') str++;
98 }
99 return NULL;
100}
101
102
103char * getl(void) {
104 char * line = malloc(128), * linep = line;
105 size_t lenmax = 128, len = lenmax;
106 int c;
107
108 if(line == NULL)
109 return NULL;
110
111 for(;;) {
112 c = fgetc(stdin);
113 if(c == EOF)
114 break;
115
116 if(--len == 0) {
117 len = lenmax;
118 char * linen = realloc(linep, lenmax *= 2);
119
120 if(linen == NULL) {
121 free(linep);
122 return NULL;
123 }
124 line = linen + (line - linep);
125 linep = linen;
126 }
127
128 if((*line = c) == '\n')
129 break;
130 line++;
131 }
132 *line = '\0';
133 return linep;
134}
135
136
137int main(int argc, char* argv[]) {
138 char* line;
139 while(line = getl()) {
140 if(*line == '\0') break;
141 if(!parse(line, 1))
142 printf("=====FAILED!=====\n\n");
143 free(line);
144 }
145 if(line) free(line);
146 return 0;
147}
diff --git a/pathologist/src/struct_parse/test.sh b/pathologist/src/struct_parse/test.sh
new file mode 100644
index 0000000..2ab8cec
--- /dev/null
+++ b/pathologist/src/struct_parse/test.sh
@@ -0,0 +1,2 @@
1#!/bin/sh
2for n in `seq 1 1000`; do zzuf -r 0.00$n -s $n -i valgrind -q --leak-check=summary --track-origins=yes ./a.out < test.txt; done
diff --git a/pathologist/src/struct_parse/test.txt b/pathologist/src/struct_parse/test.txt
new file mode 100644
index 0000000..030fe36
--- /dev/null
+++ b/pathologist/src/struct_parse/test.txt
@@ -0,0 +1 @@
{value = {publish = {pc = 0x607a20, fi = 0x60b580, cctx = 0x0, pctx = 0x0, filename = 0x60b9e0 "/home/grothoff/svn/gnunet/src/core/../../COPYING", size = 35147, eta = { rel_value = 18446744073709551615}, duration = {rel_value = 1360752708604}, completed = 0, anonymity = 1, specifics = {progress = {data = 0x0, offset = 0, data_len = 140737349529600, depth = 4158564850}, resume = {message = 0x0, chk_uri = 0x0}, completed = {chk_uri = 0x0}, error = {message = 0x0}}}, download = {dc = 0x607a20, cctx = 0x60b580, pctx = 0x0, sctx = 0x0, uri = 0x60b9e0, filename = 0x894b <Address 0x894b out of bounds>, size = 18446744073709551615, eta = {rel_value = 1360752708604}, duration = { rel_value = 0}, completed = 1, anonymity = 0, is_active = 0, specifics = {progress = {data = 0x0, offset = 140737349529600, data_len = 140737351952882, block_download_duration = { rel_value = 140733193388033}, depth = 0, respect_offered = 0, num_transmissions = 6336704}, start = {meta = 0x0}, resume = {meta = 0x0, message = 0x7ffff7b9b000 "\177ELF\002\001\001"}, error = {message = 0x0}}}, search = {sc = 0x607a20, cctx = 0x60b580, pctx = 0x0, query = 0x0, duration = {rel_value = 6339040}, anonymity = 35147, specifics = {result = {meta = 0xffffffffffffffff, uri = 0x13cd32e8bfc, result = 0x0, applicability_rank = 1}, resume_result = {meta = 0xffffffffffffffff, uri = 0x13cd32e8bfc, result = 0x0, availability_rank = 1, availability_certainty = 0, applicability_rank = 0}, update = {cctx = 0xffffffffffffffff, meta = 0x13cd32e8bfc, uri = 0x0, availability_rank = 1, availability_certainty = 0, applicability_rank = 0, current_probe_time = {rel_value = 0}}, result_suspend = {cctx = 0xffffffffffffffff, meta = 0x13cd32e8bfc, uri = 0x0}, result_stopped = {cctx = 0xffffffffffffffff, meta = 0x13cd32e8bfc, uri = 0x0}, resume = { message = 0xffffffffffffffff <Address 0xffffffffffffffff out of bounds>, is_paused = -751924228}, error = { message = 0xffffffffffffffff <Address 0xffffffffffffffff out of bounds>}, ns = {ns = 0xffffffffffffffff, name = 0x13cd32e8bfc <Address 0x13cd32e8bfc out of bounds>, root = 0x0, meta = 0x1, id = {bits = {0, 0, 0, 0, 4156141568, 32767, 4158564850, 32767, 1, 32767, 0, 0, 6336704, 0, 4156149880, 32767}}}}}, unindex = {uc = 0x607a20, cctx = 0x60b580, filename = 0x0, size = 0, eta = {rel_value = 6339040}, duration = {rel_value = 35147}, completed = 18446744073709551615, specifics = {progress = {data = 0x13cd32e8bfc, offset = 0, data_len = 1, depth = 0}, resume = {message = 0x13cd32e8bfc <Address 0x13cd32e8bfc out of bounds>}, error = {message = 0x13cd32e8bfc <Address 0x13cd32e8bfc out of bounds>}}}}, status = GNUNET_FS_STATUS_PUBLISH_START}
diff --git a/pathologist/src/struct_parse/test1.txt b/pathologist/src/struct_parse/test1.txt
new file mode 100644
index 0000000..9ddec90
--- /dev/null
+++ b/pathologist/src/struct_parse/test1.txt
@@ -0,0 +1 @@
{0 <repeats 9274 times>, -136430974, 32767, 0 <repeats 18 times>, 1560576, 0, 1560100, 0, 1560100, 0, 0, 0, 5, 0, 3657728, 0, 3678208, 0, 3677624, 0, 3696728, 0, 1560576, 0, 3, 0 <repeats 47 times>, -136436024, 32767, 0, 0, 0, 0, 0, 0, -134241024, 32767, 47, 0, -136413867, 32767, 0, 0, -134239856, 32767, 32, 0, 0, 1, -134241104, 32767, 0, 0, -8304, 32767, -136414759, 32767, -134225464, 32767, -134240992, 32767, -8304, 32767, -136431348, 32767, 1811964521, 778265193, 909012851, 1932419840, 3550831, 3550831, -136398771, 32767, 0, 0, -140067357, 32767, 0, 0, -136427454, 32767, -136478720, 32767, -136460200, 32767, -136479304, 32767, 0, 0, -8656, 32767, -134241024, 32767, 4195056, 0, -134225504, 32767, 3, 1, -8136, 0, 6, 0, 3696728, 0, 2053, 0, 1324524, 0, 1, 0, 33261, 0, 0, 0, 0, 0, 1583120, 0, 4096, 0, 3104, 0, 1349347463, 0, 0, 0, 1342975530, 0, 0, 0, 1349347464, 0 <repeats 11 times>, 4195056, 0, -134225464, 32767, -134229952, 32767, 0, 0, -134224528, 32767, 0, 0, -136427174, 32767, 0, 32767, -7304, 32767, 0, 0, 0, 0, 0, 0, -134261768, 32767, 0, 0, 7, 0, 0, 1...}
diff --git a/pathologist/src/struct_parse/test2.txt b/pathologist/src/struct_parse/test2.txt
new file mode 100644
index 0000000..e89ac3a
--- /dev/null
+++ b/pathologist/src/struct_parse/test2.txt
@@ -0,0 +1 @@
{"buil\"e" , '" ueuil \"\'', "\\\\", 0 ,1560576,0, 1560100,0 , 1560100}
diff --git a/pathologist/src/struct_parse/test3.txt b/pathologist/src/struct_parse/test3.txt
new file mode 100644
index 0000000..39bbf8c
--- /dev/null
+++ b/pathologist/src/struct_parse/test3.txt
@@ -0,0 +1 @@
{data = 0x0,offset=0, data_len= 140737349529600 ,depth =4158564850 }
diff --git a/pathologist/src/struct_parse/test4.txt b/pathologist/src/struct_parse/test4.txt
new file mode 100644
index 0000000..3735a52
--- /dev/null
+++ b/pathologist/src/struct_parse/test4.txt
@@ -0,0 +1 @@
{0 <repeats 9274 times>, -136430974, 32767, 0 <repeats 18 times>, 1560576, 0,1560100, 0, 1560100, 0, 0}
diff --git a/pathologist/src/util/Makefile.am b/pathologist/src/util/Makefile.am
new file mode 100644
index 0000000..6961228
--- /dev/null
+++ b/pathologist/src/util/Makefile.am
@@ -0,0 +1,12 @@
1INCLUDES = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include
2
3if USE_COVERAGE
4 AM_CFLAGS = --coverage -O0
5 XLIB = -lgcov
6endif
7
8lib_LTLIBRARIES = libpathologistutil.la
9
10libpathologistutil_la_SOURCES = \
11 common_allocation.c \
12 str_replace_all.c \ No newline at end of file
diff --git a/pathologist/src/util/common_allocation.c b/pathologist/src/util/common_allocation.c
new file mode 100644
index 0000000..2eef7d5
--- /dev/null
+++ b/pathologist/src/util/common_allocation.c
@@ -0,0 +1,338 @@
1/*
2 This file is part of MONKEY.
3 (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other contributing authors)
4
5 MONKEY is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 MONKEY is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with MONKEY; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/common_allocation.c
23 * @brief wrapper around malloc/free
24 * @author Christian Grothoff
25 * @author Safey A.Halim
26 */
27
28#include "monkey_common.h"
29#include <stdlib.h>
30#include <string.h>
31#include <stdarg.h>
32
33#ifndef INT_MAX
34#define INT_MAX 0x7FFFFFFF
35#endif
36
37#if 0
38#define W32_MEM_LIMIT 200000000
39#endif
40
41#ifdef W32_MEM_LIMIT
42static LONG mem_used = 0;
43#endif
44
45/**
46 * Allocate memory. Checks the return value, aborts if no more
47 * memory is available.
48 *
49 * @param size how many bytes of memory to allocate, do NOT use
50 * this function (or MONKEY_malloc) to allocate more than several MB
51 * of memory, if you are possibly needing a very large chunk use
52 * MONKEY_xmalloc_unchecked_ instead.
53 * @param filename where in the code was the call to MONKEY_malloc
54 * @param linenumber where in the code was the call to MONKEY_malloc
55 * @return pointer to size bytes of memory
56 */
57void *
58MONKEY_xmalloc_ (size_t size, const char *filename, int linenumber)
59{
60 void *ret;
61
62 /* As a security precaution, we generally do not allow very large
63 * allocations using the default 'MONKEY_malloc' macro */
64 MONKEY_assert_at (size <= MONKEY_MAX_MALLOC_CHECKED, filename, linenumber);
65 ret = MONKEY_xmalloc_unchecked_ (size, filename, linenumber);
66 if (ret == NULL)
67 {
68 fprintf (stderr, "malloc");
69 abort ();
70 }
71 return ret;
72}
73
74
75/**
76 * Allocate and initialize memory. Checks the return value, aborts if no more
77 * memory is available. Don't use MONKEY_xmemdup_ directly. Use the
78 * MONKEY_memdup macro.
79 *
80 * @param buf buffer to initialize from (must contain size bytes)
81 * @param size number of bytes to allocate
82 * @param filename where is this call being made (for debugging)
83 * @param linenumber line where this call is being made (for debugging)
84 * @return allocated memory, never NULL
85 */
86void *
87MONKEY_xmemdup_ (const void *buf, size_t size, const char *filename,
88 int linenumber)
89{
90 void *ret;
91
92 /* As a security precaution, we generally do not allow very large
93 * allocations here */
94 MONKEY_assert_at (size <= MONKEY_MAX_MALLOC_CHECKED, filename, linenumber);
95#ifdef W32_MEM_LIMIT
96 size += sizeof (size_t);
97 if (mem_used + size > W32_MEM_LIMIT)
98 return NULL;
99#endif
100 MONKEY_assert_at (size < INT_MAX, filename, linenumber);
101 ret = malloc (size);
102 if (ret == NULL)
103 {
104 fprintf (stderr, "malloc");
105 abort ();
106 }
107#ifdef W32_MEM_LIMIT
108 *((size_t *) ret) = size;
109 ret = &((size_t *) ret)[1];
110 mem_used += size;
111#endif
112 memcpy (ret, buf, size);
113 return ret;
114}
115
116
117
118/**
119 * Wrapper around malloc. Allocates size bytes of memory.
120 * The memory will be zero'ed out.
121 *
122 * @param size the number of bytes to allocate
123 * @param filename where in the code was the call to MONKEY_malloc_large
124 * @param linenumber where in the code was the call to MONKEY_malloc_large
125 * @return pointer to size bytes of memory, NULL if we do not have enough memory
126 */
127void *
128MONKEY_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber)
129{
130 void *result;
131
132#ifdef W32_MEM_LIMIT
133 size += sizeof (size_t);
134 if (mem_used + size > W32_MEM_LIMIT)
135 return NULL;
136#endif
137
138 MONKEY_assert_at (size < INT_MAX, filename, linenumber);
139 result = malloc (size);
140 if (result == NULL)
141 return NULL;
142 memset (result, 0, size);
143
144#ifdef W32_MEM_LIMIT
145 *((size_t *) result) = size;
146 result = &((size_t *) result)[1];
147 mem_used += size;
148#endif
149
150 return result;
151}
152
153
154/**
155 * Reallocate memory. Checks the return value, aborts if no more
156 * memory is available.
157 *
158 * @param ptr the pointer to reallocate
159 * @param n how many bytes of memory to allocate
160 * @param filename where in the code was the call to MONKEY_realloc
161 * @param linenumber where in the code was the call to MONKEY_realloc
162 * @return pointer to size bytes of memory
163 */
164void *
165MONKEY_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber)
166{
167#ifdef W32_MEM_LIMIT
168 n += sizeof (size_t);
169 ptr = &((size_t *) ptr)[-1];
170 mem_used = mem_used - *((size_t *) ptr) + n;
171#endif
172 ptr = realloc (ptr, n);
173 if ((NULL == ptr) && (n > 0))
174 {
175 fprintf (stderr, "realloc");
176 abort ();
177 }
178#ifdef W32_MEM_LIMIT
179 ptr = &((size_t *) ptr)[1];
180#endif
181 return ptr;
182}
183
184
185/**
186 * Free memory. Merely a wrapper for the case that we
187 * want to keep track of allocations.
188 *
189 * @param ptr the pointer to free
190 * @param filename where in the code was the call to MONKEY_array_grow
191 * @param linenumber where in the code was the call to MONKEY_array_grow
192 */
193void
194MONKEY_xfree_ (void *ptr, const char *filename, int linenumber)
195{
196 MONKEY_assert_at (ptr != NULL, filename, linenumber);
197#ifdef W32_MEM_LIMIT
198 ptr = &((size_t *) ptr)[-1];
199 mem_used -= *((size_t *) ptr);
200#endif
201 free (ptr);
202}
203
204/**
205 * Dup a string (same semantics as strdup).
206 *
207 * @param str the string to dup
208 * @param filename where in the code was the call to MONKEY_strdup
209 * @param linenumber where in the code was the call to MONKEY_strdup
210 * @return strdup(str)
211 */
212char *
213MONKEY_xstrdup_ (const char *str, const char *filename, int linenumber)
214{
215 char *res;
216
217 MONKEY_assert_at (str != NULL, filename, linenumber);
218 res = MONKEY_xmalloc_ (strlen (str) + 1, filename, linenumber);
219 memcpy (res, str, strlen (str) + 1);
220 return res;
221}
222
223
224/**
225 * Dup partially a string (same semantics as strndup).
226 *
227 * @param str the string to dup
228 * @param len the length of the string to dup
229 * @param filename where in the code was the call to MONKEY_strndup
230 * @param linenumber where in the code was the call to MONKEY_strndup
231 * @return strndup(str,len)
232 */
233char *
234MONKEY_xstrndup_ (const char *str, size_t len, const char *filename,
235 int linenumber)
236{
237 char *res;
238
239 MONKEY_assert_at (str != NULL, filename, linenumber);
240 len = MONKEY_MIN (len, strlen (str));
241 res = MONKEY_xmalloc_ (len + 1, filename, linenumber);
242 memcpy (res, str, len);
243 res[len] = '\0';
244 return res;
245}
246
247
248/**
249 * Grow an array. Grows old by (*oldCount-newCount)*elementSize bytes
250 * and sets *oldCount to newCount.
251 *
252 * @param old address of the pointer to the array
253 * *old may be NULL
254 * @param elementSize the size of the elements of the array
255 * @param oldCount address of the number of elements in the *old array
256 * @param newCount number of elements in the new array, may be 0
257 * @param filename where in the code was the call to MONKEY_array_grow
258 * @param linenumber where in the code was the call to MONKEY_array_grow
259 */
260void
261MONKEY_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
262 unsigned int newCount, const char *filename, int linenumber)
263{
264 void *tmp;
265 size_t size;
266
267 MONKEY_assert_at (INT_MAX / elementSize > newCount, filename, linenumber);
268 size = newCount * elementSize;
269 if (size == 0)
270 {
271 tmp = NULL;
272 }
273 else
274 {
275 tmp = MONKEY_xmalloc_ (size, filename, linenumber);
276 memset (tmp, 0, size); /* client code should not rely on this, though... */
277 if (*oldCount > newCount)
278 *oldCount = newCount; /* shrink is also allowed! */
279 memcpy (tmp, *old, elementSize * (*oldCount));
280 }
281
282 if (*old != NULL)
283 {
284 MONKEY_xfree_ (*old, filename, linenumber);
285 }
286 *old = tmp;
287 *oldCount = newCount;
288}
289
290
291/**
292 * Like asprintf, just portable.
293 *
294 * @param buf set to a buffer of sufficient size (allocated, caller must free)
295 * @param format format string (see printf, fprintf, etc.)
296 * @param ... data for format string
297 * @return number of bytes in "*buf" excluding 0-termination
298 */
299int
300MONKEY_asprintf (char **buf, const char *format, ...)
301{
302 int ret;
303 va_list args;
304
305 va_start (args, format);
306 ret = vsnprintf (NULL, 0, format, args);
307 va_end (args);
308 *buf = MONKEY_malloc (ret + 1);
309 va_start (args, format);
310 ret = vsprintf (*buf, format, args);
311 va_end (args);
312 return ret;
313}
314
315
316/**
317 * Like snprintf, just aborts if the buffer is of insufficient size.
318 *
319 * @param buf pointer to buffer that is written to
320 * @param size number of bytes in buf
321 * @param format format strings
322 * @param ... data for format string
323 * @return number of bytes written to buf or negative value on error
324 */
325int
326MONKEY_snprintf (char *buf, size_t size, const char *format, ...)
327{
328 int ret;
329 va_list args;
330
331 va_start (args, format);
332 ret = vsnprintf (buf, size, format, args);
333 va_end (args);
334 MONKEY_assert (ret <= size);
335 return ret;
336}
337
338/* end of common_allocation.c */
diff --git a/pathologist/src/util/str_replace_all.c b/pathologist/src/util/str_replace_all.c
new file mode 100644
index 0000000..a167523
--- /dev/null
+++ b/pathologist/src/util/str_replace_all.c
@@ -0,0 +1,56 @@
1/**
2 * vim: tabstop=2:shiftwidth=2:softtabstop=2:expandtab
3 *
4 * str_replace.c implements a str_replace PHP like function
5 * Copyright (C) 2010 chantra <chantra__A__debuntu__D__org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 * gcc -o str_replace_all str_replace_all.c
22 */
23
24#include <string.h>
25#include "monkey_common.h"
26
27char *
28MONKEY_str_replace_all ( const char *string, const char *substr, const char *replacement ){
29 char *tok = NULL;
30 char *newstr = NULL;
31 char *oldstr = NULL;
32 char *head = NULL;
33
34 /* if either substr or replacement is NULL, duplicate string a let caller handle it */
35 if ( substr == NULL || replacement == NULL ) return MONKEY_strdup (string);
36 newstr = MONKEY_strdup (string);
37 head = newstr;
38 while ( (tok = strstr ( head, substr ))){
39 oldstr = newstr;
40 newstr = MONKEY_malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 );
41 /*failed to alloc mem, free old string and return NULL */
42 if ( newstr == NULL ){
43 MONKEY_free (oldstr);
44 return NULL;
45 }
46 memcpy ( newstr, oldstr, tok - oldstr );
47 memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) );
48 memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) );
49 memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 );
50 /* move back head right after the last replacement */
51 head = newstr + (tok - oldstr) + strlen( replacement );
52 MONKEY_free (oldstr);
53 }
54 return newstr;
55}
56
diff --git a/seaspider/Makefile b/seaspider/Makefile
new file mode 100755
index 0000000..edd4681
--- /dev/null
+++ b/seaspider/Makefile
@@ -0,0 +1,3 @@
1install: seasp2_convert seasp2
2 install -t /usr/local/bin seasp2 seasp2_convert
3
diff --git a/seaspider/ignorefile.example b/seaspider/ignorefile.example
new file mode 100644
index 0000000..dad99d5
--- /dev/null
+++ b/seaspider/ignorefile.example
@@ -0,0 +1,14 @@
1# lines starting with a # are comments
2# other lines have to be in the format:
3# ^(filename)?:(functionname)?:pattern$
4# if filename or functionname is empty it matches any file / function.
5# leading and trailing whitespace will be ignored.
6
7# ignore every expression containing 'user_privatekey'
8::user_privatekey
9
10# ignore the local variable 'salt' in function 'encrypt_msg'
11:encrypt_msg:salt
12
13# ignore the variable 'mailto' in file libmail.c
14libmail.c::mailto
diff --git a/seaspider/remove_inc b/seaspider/remove_inc
new file mode 100755
index 0000000..9c55d7a
--- /dev/null
+++ b/seaspider/remove_inc
@@ -0,0 +1,30 @@
1#! /usr/bin/env python
2
3def escaped(part):
4 if part.endswith('\\'):
5 if part.endswith("\\\\"):
6 return escaped(part[:-2])
7 else:
8 return True
9 else:
10 return False
11
12def remove_increment_decrement(expr):
13 old = expr.split('"')
14 print old
15 new = [old[0]]
16 for i in range(1, len(old)):
17 if escaped(old[i-1]):
18 new[-1] += '"' + old[i]
19 else:
20 new.append(old[i])
21 for i in range(len(new)/2):
22 new[2*i] = new[2*i].replace("++", "").replace("--", "")
23 print new
24 print expr
25 print '"'.join(new)
26
27
28
29
30remove_increment_decrement('a = "--1\\"2++" + "3++ --4\\\\" + "5--\\\\\\"++6"troll')
diff --git a/seaspider/seasp2 b/seaspider/seasp2
new file mode 100755
index 0000000..ebaec86
--- /dev/null
+++ b/seaspider/seasp2
@@ -0,0 +1,21 @@
1#!/bin/bash
2
3echo "BEWARE! This is an unfinished and unstable script. use with care!"
4echo "Will start in 5..."
5sleep 1s
6echo "Will start in 4..."
7sleep 1s
8echo "Will start in 3..."
9sleep 1s
10echo "Will start in 2..."
11sleep 1s
12echo "Will start in 1..."
13sleep 1s
14
15export CC="/usr/local/bin/cparser"
16export CFLAGS="--seaspider -m32"
17./configure
18make clean
19make $1
20seasp2_convert -o expressions.sqlite
21rm -f `find * -name "*.sea"`
diff --git a/seaspider/seasp2_convert b/seaspider/seasp2_convert
new file mode 100755
index 0000000..fa4d3a0
--- /dev/null
+++ b/seaspider/seasp2_convert
@@ -0,0 +1,233 @@
1#! /usr/bin/env python
2
3import sqlite3
4import argparse
5import os
6import re
7from collections import deque
8
9
10def parseIgnores(ignfile):
11 if not ignfile:
12 return []
13
14 ignlist = []
15 ignexp = []
16 lineno = 0
17
18 lines = ignfile.readlines(100)
19 while lines:
20 for line in lines:
21 lineno += 1
22 line = line.strip()
23 if line == '' or line.startswith('#'):
24 continue
25 m = re.match(r'^([^:]*):([^:]*):(.+)$', line)
26 if not m or m.lastindex < 3:
27 print 'unknown ignore pattern on line %s: %s' % (lineno, line)
28 continue
29# ign_file = m.group(1)
30# ign_func = m.group(2)
31# ign_pattern = m.group(3)
32# ignlist.append((ign_file, ign_func, ign_pattern))
33 ignexp.append((re.compile(m.group(1)),
34 re.compile(m.group(2)),
35 re.compile(m.group(3))))
36
37 lines = ignfile.readlines(100)
38 ignfile.close()
39 return ignexp
40
41# argparse Action for a readable dir
42class readable_dir(argparse.Action):
43 def __call__(self, parser, namespace, values, option_string=None):
44 prospective_dir=values
45 if not os.path.exists(prospective_dir):
46 raise argparse.ArgumentTypeError("readable_dir:{0} is not a valid path".format(prospective_dir))
47 if os.access(prospective_dir, os.R_OK):
48 setattr(namespace, self.dest, prospective_dir)
49 else:
50 raise argparse.ArgumentTypeError("readable_dir:{0} is not a readable dir".format(prospective_dir))
51
52
53# initialize argument parser
54parser = argparse.ArgumentParser(description="converts .sea files generated by cparser to a seaspider sqlite database")
55
56parser.add_argument('--version', action='version', version='db_convert 1.0')
57parser.add_argument("-o", "--output", metavar="FILENAME",
58 type=argparse.FileType('w'), dest="outfile",
59 help="filename for the resulting sqlite database."
60 + " defaults to INPUT.sqlite")
61parser.add_argument("-i", "--ignore", metavar="FILENAME",
62 type=argparse.FileType('r'), dest="ignorefile",
63 help="filename for the ignores.")
64parser.add_argument('INPUT', nargs='?', action=readable_dir,
65 default=os.getcwd(),
66 help='input file or directory which is traversed'
67 + ' recursively. defaults to PWD')
68args = parser.parse_args()
69
70# parse ignores
71ignores = parseIgnores(args.ignorefile) or []
72
73# build output filename
74if args.outfile== None:
75 if os.path.isdir(args.INPUT):
76 in_dir = os.path.abspath(args.INPUT)
77 tmp_name = os.path.split(in_dir)[1]
78 outfilename = in_dir + '/' + tmp_name + '.sqlite'
79 elif os.path.isfile(args.INPUT):
80 outfilename = os.path.splitext(args.INPUT)[0] + '.sqlite'
81 else:
82 print 'unknown output target, writing to expressions.sqlite'
83 outfilename = 'expressions.sqlite'
84else:
85 outfilename = args.outfile.name
86 args.outfile.close()
87
88# remove old db
89try:
90 os.remove(outfilename)
91except OSError:
92 pass
93
94# connect to db
95sql_conn = sqlite3.connect(outfilename)
96sql_conn.text_factory = str
97sql_cur = sql_conn.cursor()
98
99# create table
100sql_cur.execute('''CREATE TABLE Expression (
101 expr_ID INTEGER PRIMARY KEY AUTOINCREMENT,
102 file_name TEXT NOT NULL,
103 expr_syntax TEXT,
104 start_lineno INT,
105 end_lineno INT,
106 is_call INT,
107 UNIQUE (file_name, expr_syntax, start_lineno, end_lineno))''')
108
109
110# adds an Expression to the db
111def add_expr(cur, ignores, func_name,
112 file_name, expr_syntax, start_lineno, end_lineno, is_call):
113 for i in ignores:
114 if (i[0].search(file_name) and
115 i[1].search(func_name) and
116 i[2].search(expr_syntax)):
117 return
118 vals = (file_name, expr_syntax, start_lineno, end_lineno, is_call)
119 cur.execute('INSERT OR IGNORE INTO Expression VALUES (NULL,?,?,?,?,?)', vals)
120
121
122# parses one .sea file
123def parse_sea_file(filename):
124 scope_end = []
125 scope_end.append(32767)
126 parameters = deque()
127 expr_list = []
128 prevtype = ""
129 seafile_lineno = 0
130 func_name = (32767, '')
131
132 try:
133 infile = open(filename, 'r')
134 print 'reading file: ',filename
135 except IOError:
136 print 'could not read file: ',filename
137 infile.close()
138 return
139 cfilename = os.path.split(os.path.splitext(filename)[0])[1] + '.c'
140
141 local_ignores = [ign for ign in ignores if ign[0].search(cfilename)]
142
143 lines = infile.readlines(10000)
144 while lines:
145 for line in lines:
146 seafile_lineno += 1
147 if prevtype == 'Begin-Expression':
148 if re.match(re.escape("End-Expression: " + rowfile + ':' + str(lineno) + ' ' + str(iscall)), line):
149 add_expr(sql_cur, local_ignores, func_name[1],
150 rowfile, ' '.join(expr_list), lineno, scope_end[-1], iscall)
151 prevtype = 'End-Expression'
152 expr_list.append(line.strip())
153 continue
154
155 m = re.match(r'([A-Za-z-]+): ([^:]+):(\d+) (.+)', line)
156 if not m or m.lastindex < 4:
157 print 'unknown entry type: ', filename, ' on line ', seafile_lineno
158 prevtype = ''
159 continue
160 rowtype = m.group(1)
161 rowfile = m.group(2)
162
163 if rowtype == 'SystemGlobal':
164 globalvar = m.group(4)
165 add_expr(sql_cur, ignores, func_name[1],
166 cfilename, globalvar, 0, 32767, 0)
167 elif rowtype == 'Global':
168 lineno = int(m.group(3))
169 globalvar = m.group(4)
170 add_expr(sql_cur, ignores, func_name[1],
171 rowfile, globalvar, lineno, 32767, 0)
172 elif rowtype == 'Function':
173 funame = m.group(4)
174 elif rowtype == 'Parameter':
175 if prevtype != 'Function' and prevtype != 'Parameter':
176 print 'Parameter can only follow Function or another Parameter: ', filename, ' on line ', seafile_lineno
177 lineno = int(m.group(3))
178 para = m.group(4)
179 parameters.append((rowfile, para, lineno))
180 elif rowtype == 'Scope':
181 scope_begin = int(m.group(3))
182 scope_end.append(int(m.group(4)) + 1)
183 if prevtype == 'Parameter' or prevtype == 'Function':
184 func_name = (scope_end[-1], funame)
185 while prevtype == 'Parameter':
186 try:
187 (rowfile, para, lineno) = parameters.popleft()
188 except IndexError:
189 break
190 add_expr(sql_cur, local_ignores, func_name[1],
191 rowfile, para, lineno, scope_end[-1], 0)
192 elif rowtype == 'Begin-Expression':
193 lineno = int(m.group(3))
194 iscall = int(m.group(4)[0])
195 if lineno > scope_end[-1]:
196 scope_end.pop()
197 if lineno > func_name[0]:
198 func_name = (32767, '')
199 del expr_list[:]
200 tmp = (m.group(4)[1:]).strip()
201 if len(tmp) > 0: expr_list.append(tmp)
202 else:
203 print 'unknown entry type: ', filename, ' on line ', seafile_lineno
204 prevtype = rowtype
205 sql_conn.commit()
206 lines = infile.readlines(10000)
207 infile.close()
208
209
210# traverses all .sea files in the input folder
211def traverse_sea_files(dummy, dirr, filess):
212 for child in filess:
213 if '.sea' == os.path.splitext(child)[1] and os.path.isfile(dirr+'/'+child):
214 parse_sea_file(dirr+'/'+child)
215
216
217
218# parse it
219if os.path.isdir(args.INPUT):
220 os.path.walk(os.path.abspath(args.INPUT), traverse_sea_files, 0)
221elif os.path.isfile(args.INPUT):
222 parse_sea_file(args.INPUT)
223else:
224 print 'unknown INPUT, no rows written to ',outfilename
225
226# commit changes
227sql_conn.commit()
228
229# close db
230sql_conn.close()
231
232
233