# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
-FULL_PATH_NAMES = YES
+FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
-WARN_FORMAT = "$file:$line: $text"
+WARN_FORMAT = "WARNING $file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
-WARN_LOGFILE =
+WARN_LOGFILE = doxy_warnings
#---------------------------------------------------------------------------
# configuration options related to the input files
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
-INLINE_SOURCES = YES
+INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
-COMPACT_LATEX = NO
+COMPACT_LATEX = YES
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
-PDF_HYPERLINKS = NO
+PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
-USE_PDFLATEX = NO
+USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
-GENERATE_RTF = YES
+GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# inheritance and usage relations if the target is undocumented
# or is not a class.
-HIDE_UNDOC_RELATIONS = YES
+HIDE_UNDOC_RELATIONS = NO
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
-TEMPLATE_RELATIONS = NO
+TEMPLATE_RELATIONS = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
-MAX_DOT_GRAPH_HEIGHT = 1024
+#MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_HEIGHT = 2000
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
-DOT_MULTI_TARGETS = NO
+DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
--- /dev/null
+This directory contains test data for ldc2.
\ No newline at end of file
\input req_spec
\newpage
\input impl_spec
-%\newpage
+\newpage
\input test_spec
\newpage
\input appendix
\vspace{1.5cm}
\Large -- Projektbericht --\\
\vspace{4cm}
-
-\Huge {\tt $\star$\hspace{0.5cm}LDC2\footnote{Name may be subject of change}\hspace{0.5cm}$\star$}\\
+
+\Huge {\tt $\star$\hspace{0.5cm}LDC2\hspace{0.5cm}$\star$}\\
+%\footnote{Name may be subject of change}
\vspace{1cm}
\large Honeywell Series 16\\
Object Program Analysis Tool\\
\vspace{3cm}
\large Philipp Hachtmann, Mat.-Nr. 124370 \\
\vspace{0.5cm}
-10. Dezember 2006\\
+26. März 2007\\
\vspace{3.5cm}
\normalsize Labor Softwaretechnik 2\\
Prof. Andreas Spillner\\
\section{Implementation Specification}
-\subsection{Building \pname}
+\subsection{Theory of operation}
+\subsubsection{Overview}
+
+The program is implemented using standard C++.
+
+While the data structures according to \cite{ser16:progref}
+are designed consequently object oriented,
+most of the actual processing of the data after reading in is done
+by the routines contained in
+\verb|main.cpp|, \verb|config.cpp| and \verb|tool.cpp|.
+
+Program configuration is capsuled into the class \verb|configuration_manager|,
+used by the routines in \verb|config.cpp|.
+
+\subsubsection{Program flow}
+The \verb|main()| routine sets up the working environment using the \verb|do_config()|
+subroutine contained in \verb|config.cpp|. This contains parsing the command line,
+reading a configuration file, and setting the global \verb|cfg_*| flags. The input and
+output file descriptors \verb|in_fd| and \verb|out_fd| are assigned to 0 and 1 respective
+files as stated in the configuration (command line option or configuration file).
+The \verb|configuration_manager| is able to dynamically generate help output for all
+options.
+
+The next call is \verb|read_tape()|, the data input routine. In \verb|read_tape()|,
+the static factory method \verb|tape_block::gen_from_fd()| is used to create and
+check blocks, taking data directly from the global file descriptor \verb|in_fd|.\\
+At the end of \verb|read_tape()|, the vector \verb|tape| has been filled with
+pointers to instances of \verb|tape_block|.
+
+In the next step, the routine \verb|process_tape()| is called, in which
+integrity checks on object level and splitting to files (if desired)
+are accomplished. Every valid and complete object consist of either one
+single \verb|eot_block| or a series of \verb|data_block|s, while the last block
+of each object must be one of the types which mark the end of an object.
+
+After all that, \verb|process_symbols()| is called. This routine generates three vectors
+containing symbol names: \verb|exported|, \verb|called|, and \verb|unsatisfied|.
+The latter is the difference of \verb|called| and \verb|exported|.\\
+If desired, those vectors are written out to \verb|out_fd|, one symbol per line.
+\subsubsection{Block factory}
+The software makes use of C++ virtual methods allowing for convinient processing of
+multiple kinds of blocks without knowing much about the block type currently worked
+on.\\
+The block factory consists of the static factory method \verb|tape_block::gen_from_fd()|
+and a corresponding private constructor of class \verb|tape_block|. The constructor
+creates a block and reads data from the given file descriptor. The factory method
+then tries to determine the block's type and recreate an object of the most accurate
+subtype applying to the block. Information about the block types is contained in
+the block data itself. A pointer to the newly created object is returned or one
+of the exception defined in class \verb|tape_block| is thrown.
+
+
+\subsection{Detailed documentation}
+\subsubsection{Doxygen}
+The source code has been documented using Doxygen and appropriate
+comments throughout the program code. Doxygen generates a very useful
+html documentation containing very usable diagrams (not strictly UML, but
+very fine anyway), lists and detailed documentation.
+
+The Doxygen configuration also creates man pages, latex sources with
+makefile for PostScript and PDF output.
+
+\subsubsection{Not in this document}
+I have decided not to create UML class and collaboration diagrams because
+in my opinion the Doxygen documentation perfectly covers those needs.
+
+The project already took several times the time I allocated in my schedule....
+
+\subsection{Building \pname}
\subsubsection{Build environment}
The program has been successfully built under Linux with the following
programs:
\begin{itemize}
-\item GCC version 4.1.2
-\item GNU make version 3.81
-\item Doxygen version 1.4.2
+\item GNU GCC, version 4.1.2
+\item GNU make, version 3.81
+\item Doxygen, version 1.4.2
\item Debian teTex package, version 3.0
-\item Graphviz dot version 2.8
+\item Graphviz dot tool, version 2.8
\end{itemize}
At least the the software (without docs) should be compile on any
POSIX compatible system with a fairly recent GCC and GNU make
process for the application and documentation. Changes may be
necessary to compile on a system other than stated in the last
paragraph.
-\\
To build the application, follow these easy steps:
\begin{itemize}
including binaries and documentation.
\end{itemize}
+
+% End of the show....
\ No newline at end of file
without proper end block
(\req{err001}\req{chk004}).\\
quiet & q & Suppress all non-critical messages
- to standard error (warnings, informatianal)\\
+ (warnings, informational text)\\
\hline
\end{tabular}\end{center}
\caption{Configuration switches}
\section{Test Specification}
---- To be done ---
\ No newline at end of file
+There is currently no test specification. Most of the functionality
+has been tested manually using the objects contained in the \verb|/data|
+subdirectory.\\
*
* LDC2 source code
*
- * $Date: 2007/03/26 01:15:21 $
+ * $Date: 2007/03/26 03:20:31 $
* $Author: hachti $
*
* $Log: main.cpp,v $
- * Revision 2.1 2007/03/26 01:15:21 hachti
+ * Revision 2.2 2007/03/26 03:20:31 hachti
+ * *** empty log message ***
+ *
+ * Revision 2.1 2007-03-26 01:15:21 hachti
* *** empty log message ***
*
* Revision 2.0 2007-03-26 01:00:40 hachti
/******************************************************************************/
-static FILE * stdwarn; //! Suppressable warning output file pointer.
-static vector<tape_block*> tape; //! Represents the whole tape contents.
+static FILE * stdwarn; //! Suppressable warning output file pointer.
+static vector<tape_block*> tape; //! The whole tape contents.
static vector<vector<tape_block*> > objects; //! Tape content in objects.
-static int errors=0;
-static int warnings=0;
-static int errcode=0; //! Variable for error codes.
+static int errors = 0; //! Global error counter.
+static int warnings= 0; //! Global warning counter.
+static int errcode = 0; //! Error code for error exit routine.
+
/******************************************************************************/
/*!
exit(errcode);
}
}
+
/******************************************************************************/
/*!
while(read_ahead){
- bool err_checksum=false;
- bool err_integrity=false;
+ bool err_checksum=false; //! Checksum error flag.
+ bool err_integrity=false; //! Integrity error flag.
- bool warning=false;
- bool error=false;
+ bool warning=false; //! Warning flag.
+ bool error=false; //! Error flag.
+ // Try to generate block
try{
block=tape_block::gen_from_fd(in_fd);
}
catch(tape_block::io_error_exception){
if (in_fd){
- fprintf(stderr,"Error: Could not read from \"%s\"!\n",cfg_infile.c_str());
+ fprintf(stderr,"Error: Could not read from \"%s\"!\n",
+ cfg_infile.c_str());
} else {
fprintf(stderr,"Error: Could not read from stdin!\n");
}
/******************************************************************************/
+/*!
+ *\brief Do integrity test and object or block dumps.
+ */
void process_tape(){
- if (cfg_verbose) fprintf(stdwarn,"Processing Tape.\n");
+ if (cfg_verbose) fprintf(stdwarn,"\nProcessing Data.\n");
bool in_object=false;
char filename[100];
objname="EOT";
if (in_object){
if (cfg_ignore_object_integrity_errors){
- fprintf(stdwarn,"Warning: Object integrity error!\n");
+ fprintf(stdwarn,"Warning: Object integrity error!\
+ (Object no %i, Block %i unexpected)\n",obj_no,i);
warnings++;
} else {
fprintf(stderr,"Error: Object integrity error!\
}
}
}
-
if (!in_object){ // object begin
+
obj_no++;
obj_start_block=i;
objname=objname.substr(0,objname.find_last_not_of(" ")+1);
unknown_count--;
break;
-
}
}
// Open file for split objects
if (cfg_split_objects && (block->get_type()!=tape_block::TBT_EOT)){
- if (objname=="UNKNOWN")snprintf(filename,99,"UNKNOWN%02i.obj",unknown_count);
+ if (objname=="UNKNOWN")snprintf(filename,99,"UNKNOWN%02i.obj",
+ unknown_count);
else snprintf(filename,99,"%s.obj",objname.c_str());
if (fd>-1) close (fd);
+ if (cfg_verbose) fprintf(stdwarn,"Writing file: %s\n",filename);
fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
- printf("opening \"%s\"\n",filename);
if (fd<0){
fprintf(stderr,"Error: could not open file \"%s\" for writing!\n",
filename);
// Open file for split objects numbered
snprintf(filename_numbered,99,"%03i0-%s.obj",obj_no,objname.c_str());
if (cfg_split_objects_numbered){
- if (fd_numbered>-1) close (fd_numbered);
+ close (fd_numbered);
+ if (cfg_verbose) fprintf(stdwarn,"Writing file: %s\n",filename_numbered);
fd_numbered=open(filename_numbered,O_WRONLY|O_CREAT|O_TRUNC,0666);
if (fd_numbered<0){
fprintf(stderr,"Error: could not open file \"%s\" for writing!\n",
// Output individual block file if desired
if (cfg_split_blocks){
char fname[100];
- snprintf(fname,99,"%03i0-%s-%03i.block",obj_no,objname.c_str(),i-obj_start_block);
+ snprintf(fname,99,"%03i0-%s-%03i.block",obj_no,objname.c_str(),
+ i-obj_start_block);
+ if (cfg_verbose) fprintf(stdwarn,"Writing file: %s\n",fname);
int fd_block=open(fname,O_WRONLY|O_TRUNC|O_CREAT,0666);
if (fd_block<0){
fprintf(stderr,"Error: could not open file \"%s\" for writing!\n",
fname);
errors++;
errcode=1;
+ close(fd);
+ close(fd_numbered);
return;
}
try{
fname);
errors++;
errcode=1;
+ close(fd);
+ close(fd_numbered);
return;
}
close(fd_block);
if (block->is_endblock()||(block->get_type()==tape_block::TBT_EOT)) {
in_object=false;
- if (fd!=-1) close(fd);
- if (fd_numbered!=-1) close(fd_numbered);
+ close(fd);
+ close(fd_numbered);
}
} // for (...)
if (in_object){
if (cfg_ignore_object_integrity_errors){
- fprintf(stdwarn,"Warning: Object integrity error!\n");
+ fprintf(stdwarn,"Warning: Object integrity error! Last object incomplete!\n");
warnings++;
} else {
- fprintf(stdwarn,"Error: Object integrity error!\n");
+ fprintf(stdwarn,"Error: Object integrity error! Last Object incomplete!\n");
errors++;
errcode=6;
+ if (fd!=-1) close(fd);
+ if (fd_numbered!=-1) close(fd_numbered);
return;
}
}
/*!
*\brief Everything that has to do with symbol listing.
*/
-void process_called_imports(){
+void process_symbols(){
vector<string>exported;
vector<string>called;
vector <string>unsatisfied;
-
+
+ if (cfg_verbose) fprintf(stdwarn,"\nProcessing Symbols.\n");
+
for (unsigned int i=0; i<tape.size();i++){
merge_vector_unique(exported,tape[i]->get_exported_symbols());
merge_vector_unique(called,tape[i]->get_called_symbols());
dump_vector_fp(unsatisfied,outp);
}
-}
+} // process_symbols()
/******************************************************************************/
/*!
process_tape();
exit_on_error();
- process_called_imports();
+ process_symbols();
exit_on_error();
-
-
+
if (warnings>0){
fprintf(stdwarn,"Warnings:%i\n",warnings);
return 99;
}
- if (cfg_verbose) fprintf(stdwarn,"Success.\n");
+ if (cfg_verbose) fprintf(stdwarn,"\nSuccess.\n");
return 0;
+
+ /*
+ * All over this program, no memory is freed. This is not necessary because
+ * everything is allocated once and that's it.
+ * The classes support proper freeing of their internal buffers.
+ */
+
} // main()
+/******************************************************************************/
*
* LDC2 source code
*
- * $Date: 2007/03/26 01:00:40 $
+ * $Date: 2007/03/26 03:20:31 $
* $Author: hachti $
*
* $Log: tape_block.cpp,v $
- * Revision 2.0 2007/03/26 01:00:40 hachti
+ * Revision 2.1 2007/03/26 03:20:31 hachti
+ * *** empty log message ***
+ *
+ * Revision 2.0 2007-03-26 01:00:40 hachti
* *** empty log message ***
*
*
******************************************************************************/
-
-
#include <string>
#include <vector>
/*!
*\brief Access internal raw data buffer
*
- * The raw data buffer contains all block data except the \ \
- * block start delimiter and block end delimiter.
+ * The raw data buffer contains all block data except the
+ * block start and end delimiters.
*\return Pointer to internal raw data buffer of the block
*/
unsigned char * tape_block::get_raw_data(){
/***************************************************************/
/*!
*\brief Get amount of consumed data before EOF came along.
- *\return Amound of bytes read from fd while looking for
+ *\return Amount of bytes read from fd while looking for
* new block or EOF.
*/
int tape_block::eof_legal_exception::get_consumed(){