CCFLAGS+=-Wall
-
BUILD_STAMP="\"`uname -a`\""
VERSION="\"0.7\""
BUILD_DATE="\"`date` \""
default: $(APP_NAME)
+
clean:
@rm -rf $(APP_NAME) *.o doxy/ $(SRC_DIR)/*~ ul_timestamp *.dep
@$(MAKE) -C doc clean
--- /dev/null
+C APFELMAENNCHEN-PROGRAMM, 02.APRIL.2006 PHILIPP HACHTMANN
+C INTERMEDIATE VERSION
+C
+C THIS VERSION SHOULD RUN A BIT FASTER BECAUSE THE SQUARE
+C ROOT IS OMMITTED.
+C
+C SWITCH SETTINGS:
+C SENSE-SWITCH 1: IF SET, ASK FOR PARAMETERS
+C SENSE-SWITCH 2: IF SET, DON'T PRINT PARAMETERS ON START
+C SENSE-SWITCH 3: IF SET, RESTORE PARAMETERS TO DEFAULT VALUES
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+C COMMON BLOCK DECLARATIONS
+C
+ INTEGER MAXI,WIDTH,CR,LF,POSI,NEGA
+ COMMON /PARAM2/MAXI,WIDTH,CR,LF,POSI,NEGA
+C
+ REAL LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ COMMON /PARAM1/LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+C
+ INTEGER INIT
+ COMMON /PARAM3/INIT
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+C START MESSAGE
+ 100 WRITE (1,10)
+ 10 FORMAT (46HMANDELBROT-DEMO 3RC1 02.04.2006, PH. HACHTMANN,
+ + 20H - PRELIMIMARY ISSUE)
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+C CONFIGURATION
+CCCCCC RESET DO DEFAULT VALUES?
+ 110 CALL SSWTCH(3,I)
+ IF (I.EQ.1) CALL RST
+C
+CCCCCC ON THE FIRST START OR IF DESIRED
+ IF(INIT.EQ.0) CALL STVAL
+C
+CCCCCC DO WE HAVE TO ASK FOR PARAMETERS?
+ CALL SSWTCH(1,I)
+ IF (I.EQ.1) CALL GETCFG
+C
+CCCCCC OUTPUT SETTINGS?
+ CALL SSWTCH(2,I)
+ IF(I.EQ.2) CALL OUTCFG
+C
+ WRITE (1,55)
+ 55 FORMAT (1H0)
+C
+ CALL CALC2
+C
+ WRITE(1, 60)
+ 60 FORMAT (5HREADY)
+C
+CCCCCC BREAK WITH 7 in A REG, THEN START OVER
+C CALL PWAIT
+ PAUSE 7
+ GO TO 100
+ END
+C END OF MAIN PROGRAM
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+CCCCCC THE MANDELBROT SET CALCULATION
+ SUBROUTINE CALC2
+C
+ INTEGER MAXI,WIDTH,CR,LF
+ COMMON /PARAM2/MAXI,WIDTH,CR,LF
+ REAL LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ COMMON /PARAM1/LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ REAL CMPAVL
+ REAL ZR,ZI,ZRN
+ REAL X,Y
+ INTEGER COUNT
+C
+CCCCCC ENTER THE CALCULATION
+ 299 CMPVAL=MAXVAL*MAXVAL
+ X=LOWX
+ Y=HIGHY
+C
+CCCCCC EINSTIEG IN DEN AKTUELLEN PUNKT
+ 300 COUNT=0
+ ZR=0.0
+ ZI=0.0
+C
+CCCCCC HIER DER ITERIERTE TEIL
+C
+ 400 ZRN=ZR*ZR-ZI*ZI+X
+ ZI=2.0*ZR*ZI+Y
+ ZR=ZRN
+C
+ IF ((ZR*ZR+ZI*ZI).GE.CMPVAL) GO TO 410
+ COUNT=COUNT+1
+ IF (COUNT.GE.MAXI) GO TO 410
+ GO TO 400
+C
+CCCCCC PUNKT FERTIG
+ 410 NOUT=32
+C IF (COUNT.GE.8) NOUT=46
+C IF (COUNT.GE.23) NOUT=43
+C IF (COUNT.EQ.MAXI) NOUT=64
+ IF (COUNT.GE.8) NOUT=46
+ IF (COUNT.GE.23) NOUT=43
+ IF (COUNT.EQ.MAXI) NOUT=64
+
+ 411 CALL PCHAR(NOUT)
+ GO TO 500
+C
+CCCCCC NEUEN PUNKT MACHEN
+ 500 X = X + XSTEP
+CCCCCC ZEILE NOCH NICHT VOLL?
+ IF (X.LE.HIGHX) GO TO 300
+CCCCCC X AN ANFANG SETZTEN, CR+LF DRUCKEN
+ X = LOWX
+ CALL PCHAR(CR)
+ CALL PCHAR(LF)
+CCCCCC Y WEITERRUECKEN - NEGATIV WEIL WIR VON OBEN KOMMEN
+ Y=Y-YSTEP
+ IF (Y.GE.LOWY) GO TO 300
+C
+CCCCCC HIER IST DAS BILD FERTIG.
+ RETURN
+ END
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+CCCCCC STARTWERTE AUSFUELLEN
+ SUBROUTINE STVAL
+C
+ INTEGER MAXI,WIDTH,CR,LF
+ COMMON /PARAM2/MAXI,WIDTH,CR,LF
+ REAL LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ COMMON /PARAM1/LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ INTEGER INIT
+ COMMON /PARAM3/INIT
+C
+ CR = 13
+ LF = 10
+ WIDTH = 68
+ MAXI = 60
+ MAXVAL = 2.0
+ LOWX =-1.48
+ HIGHX = 0.5
+ LOWY =-1.2
+ HIGHY = 1.2
+ INIT = 1
+C
+CCCCCC SCHRITTWEITEN AUSRECHNEN
+ XSTEP = (HIGHX-LOWX)/FLOAT(WIDTH)
+ YSTEP = 2.0 * XSTEP
+C
+ WRITE (1,1500)
+ 1500 FORMAT (20HDEFAULT VALUES USED.)
+ RETURN
+ END
+C
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+CCCCCC EINSTELLUNGEN EINLESEN
+ SUBROUTINE GETCFG
+C
+ INTEGER MAXI,WIDTH,CR,LF
+ COMMON /PARAM2/MAXI,WIDTH,CR,LF
+ REAL LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ COMMON /PARAM1/LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+C
+ REAL XIN1,XIN2,YIN1,YIN2
+C
+ WRITE(1,11)
+ READ (1,16) XIN1
+ WRITE(1,12)
+ READ (1,16) XIN2
+ WRITE(1,13)
+ READ (1,16) YIN1
+ WRITE(1,14)
+ READ (1,16) YIN2
+ WRITE(1,15)
+ READ (1,17) MAXI
+C
+ 11 FORMAT(14H X FROM : )
+ 12 FORMAT(14H TO : )
+ 13 FORMAT(14H Y FROM : )
+ 14 FORMAT(14H TO : )
+ 15 FORMAT(14H MAXIT (I3): )
+ 16 FORMAT(F12.0)
+ 17 FORMAT(I3)
+C
+CCCCCC EVENTUELL STARTWERTE TAUSCHEN:
+CCCCCC WENN XIN2 GROESSER IST OK, ANSONSTEN TAUSCHEN
+ 150 I F(XIN2.GT.XIN1) GO TO 200
+ TEMP = XIN1
+ XIN1 = XIN2
+ XIN2 = TEMP
+C
+CCCCCC WENN YIN2 GROESSER IST OK, ANSONSTEN TAUSCHEN
+ 200 IF(YIN2.GT.YIN1) GO TO 201
+ TEMP = YIN1
+ YIN1 = YIN2
+ YIN2 = TEMP
+C
+CCCCCC WERTE UEBERNEHMEN
+ 201 LOWX = XIN1
+ HIGHX = XIN2
+ LOWY = YIN1
+ HIGHY = YIN2
+C
+CCCCCC SCHRITTWEITEN AUSRECHNEN
+ XSTEP = (HIGHX-LOWX)/FLOAT(WIDTH)
+ YSTEP = 2.0 * XSTEP
+C
+ RETURN
+ END
+C
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+CCCCCC EINSTELLUNGEN AUSGEBEN
+ SUBROUTINE OUTCFG
+C
+ INTEGER MAXI,WIDTH,CR,LF
+ COMMON /PARAM2/MAXI,WIDTH,CR,LF
+ REAL LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+ COMMON /PARAM1/LOWX,LOWY,HIGHX,HIGHY,MAXVAL,XSTEP,YSTEP
+C
+ WRITE (1,20)
+ 20 FORMAT (9HSETTINGS:)
+ WRITE (1,30) LOWX, HIGHX
+ 30 FORMAT (12HX-WERTE VON ,1F8.5,5H BIS ,1F8.5)
+ WRITE (1,40) LOWY, HIGHY
+ 40 FORMAT (12HY-WERTE VON ,F8.5,5H BIS ,F8.5)
+ WRITE (1,50) MAXI, MAXVAL, XSTEP, YSTEP, WIDTH
+ 50 FORMAT ( 4HMAX:,I3,
+ + 8H MAXVAL:,F8.5,
+ + 7H XSTEP:,F8.5,
+ + 7H YSTEP:,F8.5,
+ + 7H WIDTH:,I2)
+ RETURN
+ END
+C
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+CCCCCC RUECKSETZEN
+ SUBROUTINE RST
+C
+ INTEGER MAXI,WIDTH,CR,LF
+ COMMON /PARAM2/MAXI,WIDTH,CR,LF
+C
+ WRITE(1,245)
+ 245 FORMAT(25HPARAMETER RESET REQUESTED)
+ INIT=0
+ RETURN
+ END
+C
+C
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+C PRELOAD VALUE OF INIT
+ BLOCK DATA
+ INTEGER INIT
+ COMMON /PARAM3/INIT
+ DATA INIT/0/
+ END
+CCCCCCCCCCCCCCCCCCCCCCCC
+$0
There shall be a possibility to suppress warning messages.
}
+\rd{err006}{Informational messages}{
+ Any informational messages go to standard error.
+}
+
+
%*******************************************************************************
\newpage
\subsection{Program configuration}
ignore\_object\_integrity\_errors & g & Ignore errors caused by objects
without proper end block
(\req{err001}\req{chk004}).\\
+ quiet & q & Suppress all non-critical messages
+ to standard error (warnings, informatianal)\\
\hline
\end{tabular}\end{center}
\caption{Configuration switches}
| "ignore_block_errors" | "ignore_checksum_errors
| "pause_on_checksum_error"
| "ignore_unknown_block_errors"
- | "ignore_object_integrity" ;
+ | "ignore_object_integrity"
+ | "quiet" ;
StrLong = "out_file" | "in_file" ;
BoolValue = TrueStr | FalseStr ;
String = { ? Every character except newline ?} ;
ShortParam = "-" StrShort String ;
LongParam = "--" StrLong "=" String ;
SwShort = "h" | "a" | "c" | "e" | "u" | "s" | "S"
- | "b" | "k" | "p" | "n" | "g" ;
+ | "b" | "k" | "p" | "n" | "g" | "q";
SwLong = "help"
| "output_info" | "ouput_called" | "output_exported"
| "output_unsatisfied" | "split_objects" [ _"numbered" ]
| "ignore_block_errors" | "ignore_checksum_errors"
| "pause_on_checksum_error"
| "ignore_unknown_block_errors"
- | "ignore_object_integrity" ;
+ | "ignore_object_integrity"
+ | "quiet" ;
StrShort = "o" ;
StrLong = "out_file" ;
\end{verbatim}
\item \emph{pause\_on\_checksum\_errors} implies \emph{ignore\_checksum\_errors}.
\item \emph{pause\_on\_checksum\_errors} is completely ignored when input
is read from standard input.
- \item \emph{output\_*} inhibits tape information output (\req{da001}).
+ \item \emph{output\_*} and \emph{split\_*} inhibit
+ tape information output (\req{da001}).
\item \emph{help} inhibits all other actions.
\end{itemize}
}
\item Data is read from standard input.
\item All error conditions result in immediate program termination
and an error message.
- \item Tape information according to \req{da001} is output.
- \item Normal Text is output to standard output.
- \item Error messages are output to standard error.
+ \item Tape information according to \req{da001} is output to standard output.
\end{itemize}
}
--- /dev/null
+
+# This tells the program to be a bit more quiet.
+quiet=1
+
+verbose=1
\ No newline at end of file
int cfg_output_called=0;
int cfg_output_exported=0;
int cfg_output_unsatisfied=0;
-int cfg_splitobjects=0;
-int cfg_splitobjects_numbered=0;
+int cfg_split_objects=0;
+int cfg_split_objects_numbered=0;
int cfg_ignore_block_errors=0;
int cfg_ignore_checksum_errors=0;
int cfg_pause_on_checksum_error=0;
int cfg_ignore_object_integrity_errors=0;
int cfg_list_contents=1;
int cfg_verbose=0;
+int cfg_quiet=0;
+
int cfg_version=0;
int in_fd=0; //! File descriptor for data input
-int out_fd=1; //! File descriptor for text output
-
+int out_fd=2; //! File descriptor for text output
void do_config(int argc, char ** args){
ar.add_option_switch("S","split_objects_numbered",
"Split input data into distinct numbered files",
- &cfg_splitobjects_numbered,true,true);
+ &cfg_split_objects_numbered,true,true);
ar.add_option_switch("s","split_objects",
"Split input data into distinct object files.",
- &cfg_splitobjects,true,true);
+ &cfg_split_objects,true,true);
ar.add_option_switch("b","ignore_block_errors",
"Ignore block integrity errors. This will output broken blocks,too",
&cfg_ignore_object_integrity_errors,true,true);
ar.add_option_switch("v","verbose",
- "Be a bit more verbose.",
+ "Be a bit more verbose. This overrides -q.",
&cfg_verbose,true,true);
+ ar.add_option_switch("q","quiet",
+ "Be quiet. All warning messages are suppressed.",
+ &cfg_quiet,true,true);
+
ar.add_option_switch("V","version",
"Output version information and exit.",
&cfg_version,false,true);
// If there's a config file mentioned in the environment, take it!
char * env_ldc_config=getenv("LDC_CONFIG");
if(env_ldc_config){
- fprintf(stderr,"Using config file: \"%s\"\n",env_ldc_config);
- if(dump_vector_err(ar.read_file(env_ldc_config))){
- dump_vector_err(ar.get_help());
+ if (cfg_verbose) fprintf(stderr,"Using config file: \"%s\"\n",env_ldc_config);
+ if(dump_vector_fp(ar.read_file(env_ldc_config),stderr)){
+ dump_vector_fp(ar.get_help(),stderr);
exit(1);
}
}
// Process command line first time
- if(dump_vector_err(ar.read_args(argc,args))){
- dump_vector_err(ar.get_help());
+ if(dump_vector_fp(ar.read_args(argc,args),stderr)){
+ dump_vector_fp(ar.get_help(),stderr);
exit(7);
}
if (cfg_do_help) {
- dump_vector_err(ar.get_help());
+ dump_vector_fp(ar.get_help(),stderr);
exit(0);
}
if (cfg_config_file_set){
if (cfg_verbose)
fprintf(stderr,"Using config file: \"%s\"\n",cfg_config_file.c_str());
- if(dump_vector_err(ar.read_file(cfg_config_file))){
- dump_vector_err(ar.get_help());
+ if(dump_vector_fp(ar.read_file(cfg_config_file),stderr)){
+ dump_vector_fp(ar.get_help(),stderr);
exit(7);
}
// Process command line a second time to override values from config file.
- if(dump_vector_err(ar.read_args(argc,args))||cfg_do_help){
- dump_vector_err(ar.get_help());
+ if(dump_vector_fp(ar.read_args(argc,args),stderr)||cfg_do_help){
+ dump_vector_fp(ar.get_help(),stderr);
exit(7);
}
}
}
}
+ // Verbose overrides quiet:
+ if (cfg_verbose)cfg_quiet=0;
+
// The configuration implications according to /cfg007/
if (in_fd==0) cfg_pause_on_checksum_error=0;
if (cfg_pause_on_checksum_error==1) cfg_ignore_checksum_errors=1;
- if (cfg_output_info||cfg_output_called||cfg_output_exported||cfg_output_unsatisfied)
+ if (cfg_output_info||cfg_output_called||cfg_output_exported||
+ cfg_output_unsatisfied||
+ cfg_split_objects||cfg_split_objects_numbered)
cfg_list_contents=0;
}
extern int cfg_output_called;
extern int cfg_output_exported;
extern int cfg_output_unsatisfied;
-extern int cfg_splitobjects;
-extern int cfg_splitobjects_numbered;
+extern int cfg_split_objects;
+extern int cfg_split_objects_numbered;
extern int cfg_ignore_block_errors;
extern int cfg_ignore_checksum_errors;
extern int cfg_pause_on_checksum_error;
extern int cfg_list_contents;
extern int cfg_verbose;
extern int cfg_version;
+extern int cfg_quiet;
extern int in_fd; //! File descriptor for data input
extern int out_fd; //! File descriptor for text output
using namespace std;
+/***************************************************************/
/*!
*\brief Specialisation constructor.
*/
data_block::data_block(tape_block& org)
:tape_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+/***************************************************************/
/*!
*\brief Determine block type.
*\return the block type extracted from the block's data.
return (word_data[0]&0xf000)>>12;
}
+/***************************************************************/
/*!
*\brief Get the block's size in 16 bit words.
*\return The block's 16-bit data buffer's size including
return word_size;
}
+/***************************************************************/
/*!
*\brief Describe the block.
*\return A vector of text lines describing this block.
return result;
}
-/*!
- *\brief Determine if the block marks the end of an object
- *\retval true The block marks the end of an object.
- *\retval false The block does not mark the end of an object.
- */
-bool data_block::get_obj_end(){
- return false;
-}
-
+/***************************************************************/
/*!
*\brief Extract 6 byte symbol name from word memory.
*
return result;
}
+
+
+
int get_type();
int get_word_size();
virtual vector<string> get_description();
- virtual bool get_obj_end();
+
protected:
string extract_label(int);
};
*/
data_block_0::data_block_0(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
* Determine the block's subtype.
-#ifndef DATA_BLOCK_0_H
-#define DATA_BLOCK_0_H
+#ifndef DATA_BLOCK_0_HH
+#define DATA_BLOCK_0_HH
#include <vector>
#include <string>
*/
data_block_0_0::data_block_0_0(data_block_0 & org)
:data_block_0_label_extractor(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
return result;
}
+/***************************************************************/
+/*!
+ *\brief Get exported symbols.
+ *\return A vector containing the symbol names exported by this
+ * block.
+ */
+vector<string> data_block_0_0::get_exported_symbols(){
+ return get_labels();
+}
+
void(*)(void*),void*);
public:
vector<string> get_description();
+ vector<string> get_exported_symbols();
protected:
data_block_0_0(data_block_0&);
*/
data_block_0_1::data_block_0_1(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
*/
data_block_0_10::data_block_0_10(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_0_14::data_block_0_14(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
return result;
}
+/***************************************************************/
+/*!
+ *\brief Determine if the block marks the end of an object
+ *\return true because this block is an end block.
+ */
+bool data_block_0_14::is_endblock(){
+ return true;
+}
+
void(*)(void*),void*);
public:
vector<string> get_description();
+ bool is_endblock();
protected:
data_block_0_14(data_block_0&);
*/
data_block_0_2::data_block_0_2(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
*/
data_block_0_24::data_block_0_24(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_0_3::data_block_0_3(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
*/
data_block_0_30::data_block_0_30(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_0_4::data_block_0_4(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
*/
data_block_0_44::data_block_0_44(data_block_0 & org)
:data_block_0_label_extractor(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
label+" "+get_typestring()+"Subprogram Call");
return result;
}
+
+/***************************************************************/
+/*!
+ *\brief Get called symbols.
+ *\return A vector containing the symbol names called by this
+ * block.
+ */
+vector<string> data_block_0_44::get_called_symbols(){
+ vector<string> result;
+ result.insert(result.end(),get_labels()[0]);
+ return result;
+}
void(*)(void*),void*);
public:
vector<string> get_description();
+ vector<string> get_called_symbols();
protected:
data_block_0_44(data_block_0&);
*/
data_block_0_50::data_block_0_50(data_block_0 & org)
:data_block_0_label_extractor(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_0_54::data_block_0_54(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_0_60::data_block_0_60(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_0_64::data_block_0_64(data_block_0 & org)
:data_block_0(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
*/
data_block_1::data_block_1(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
*\brief Specialisation constructor.
*/
data_block_2::data_block_2(data_block & org)
- :data_block(org){}
+ :data_block(org)
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
*/
data_block_3::data_block_3(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
return result;
}
+/***************************************************************/
+/*!
+ *\brief Determine if the block marks the end of an object
+ *\return true because this block is an end block.
+ */
+bool data_block_3::is_endblock(){
+ return true;
+}
+
public:
vector<string> get_description();
+ bool is_endblock();
};
#endif
*/
data_block_4::data_block_4(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
return result;
}
+/***************************************************************/
+/*!
+ *\brief Determine if the block marks the end of an object
+ *\return true because this block is an end block.
+ */
+bool data_block_4::is_endblock(){
+ return true;
+}
+
public:
vector<string> get_description();
+ bool is_endblock();
};
#endif
*/
data_block_5::data_block_5(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
return result;
}
+/***************************************************************/
+/*!
+ *\brief Get called symbols.
+ *\return A vector containing the symbol names exported by this
+ * block.
+ */
+vector<string> data_block_5::get_called_symbols(){
+ vector<string> result;
+ result.insert(result.end(),extract_label(3));
+ return result;
+}
+
public:
vector<string> get_description();
+ vector<string> get_called_symbols();
};
#endif
*/
data_block_6::data_block_6(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
+
/*!
*\brief Describe the block.
return result;
}
-
+/***************************************************************/
+/*!
+ *\brief Get exported symbols.
+ *\return A vector containing the symbol names exported by this
+ * block.
+ */
+vector<string> data_block_6::get_exported_symbols(){
+ vector<string> result;
+ result.insert(result.end(),extract_label(3));
+ return result;
+}
public:
vector<string> get_description();
+ vector<string> get_exported_symbols();
};
#endif
*/
data_block_7::data_block_7(data_block & org)
:data_block(org)
-{}
+{
+ m_has_known_type=false;
+}
/*!
*\brief Describe the block.
return result;
}
+/***************************************************************/
+/*!
+ *\brief Get called symbols.
+ *\return A vector containing the symbol names exported by this
+ * block.
+ */
+vector<string> data_block_7::get_called_symbols(){
+ vector<string> result;
+ result.insert(result.end(),extract_label(3));
+ return result;
+}
public:
vector<string> get_description();
+ vector<string> get_called_symbols();
+
};
#endif
*/
eot_block::eot_block(eot_block & org){
operator=(org);
+ m_has_known_type=true;
}
/***************************************************************/
public: // methods
eot_block(eot_block &);
virtual vector<string> get_description();
-
private: // methods
eot_block(tape_block &);
eot_block();
#define BLOCK_END_DELIMITER_1 0223 // XOFF 0x93
#define BLOCK_END_DELIMITER_2 0xFF
-
/* End of Tape sequence
* If EOT_LENGTH is set to 2, EOT_1 becomes insignificant and so on
*/
#define EOT_SEQ_2 0x93
#define EOT_SEQ_3 0xff
-
#endif
#define VERSION "0.0"
#endif
-#define ID_STRING "\n ldc2 - The X16 object analyser\n\
+#define ID_STRING "\n ldc2 - The X16 object tape analyser\n\
(C) 2007 Philipp Hachtmann\n\n\
Version %s, built %s\n %s\n\n"
+/******************************************************************************/
+static FILE * stdwarn; //! Suppressable warning output file pointer.
+static vector<tape_block*> tape; //! Represents the whole tape contents.
+static vector<vector<tape_block*> > objects; //! Tape content in objects.
-/*!
- *\brief The main routine.
- */
-int main(int argc, char ** args){
+static int errors=0;
+static int warnings=0;
+static int errcode=0; //! Variable for error codes.
-
- // Do all the configuration stuff
- do_config(argc,args);
-
- if (cfg_version){
- fprintf(stderr, ID_STRING, VERSION, BUILD_DATE, BUILD_STAMP);
- exit(0);
+
+void exit_on_error(){
+ if (errors){
+ fprintf(stderr,"Failed. (%i)\n",errcode);
+ exit(errcode);
}
+}
- vector<tape_block*> tape;
- vector<vector<tape_block *> > objects;
- vector<tape_block *> current_object;
+/******************************************************************************/
+/*!
+ *\brief Read in Tape data and do some checks and messages.
+ *
+ * This routine reads in the tape data.
+ * During reading in, checksums are checked and
+ * /da001/ information is generated. No object integrity test.
+ * Tape block object pointers are put into the global vector
+ * tape.
+ */
+void read_tape(){
+
+ tape_block * block=0; //! Pointer to current block.
+ bool read_ahead=true; //! Continue scanning for blocks.
+ int read_pointer=0; //! Read position in input.
+ int block_start=0; //! Start of block position in input.
+ int block_end=0; //! End of block position in input.
+ int blocks_read=0; //! Number of blocks read in.
- tape_block * block=0;
- bool read_ahead=true;
-
- int read_pointer=0;
- int block_start=0;
- int block_end=0;
- int blocks_read=0;
-
- bool in_object=false;
-
- int errors=0;
- int warnings=0;
- int errcode=0;
-
- bool spaced=false;
+ bool spaced=false; //! Help flag for spaced messages.
+
+ string message; //! A warning or help message.
+
while(read_ahead){
+
+ bool err_checksum=false;
+ bool err_integrity=false;
+
+ bool warning=false;
+ bool error=false;
+
try{
block=tape_block::gen_from_fd(in_fd);
- blocks_read++;
- tape.insert(tape.end(),block);
- block_start=read_pointer+block->get_discarded_bytes();
- block_end=block_start+block->get_raw_size()-1;
- read_pointer=block_end+1;
-
- if (cfg_verbose) {
- char buffer[200];
- if (!spaced) fprintf(stderr,"\n");
- spaced=false;
-
- snprintf(buffer,200,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
- blocks_read-1,
- block_start,
- block_end,
- block->get_raw_size());
- fprintf(stderr,buffer);
- }
- if(cfg_list_contents)
- dump_vector(block->get_description());
}
catch(tape_block::eof_legal_exception &e){
} else {
fprintf(stderr,"Error: Could not read from stdin!\n");
}
- errors++;
+ error=true;
errcode=2;
break; // Immediately leave read loop.
}
catch(tape_block::eof_illegal_exception &e){
block=e.get_block();
- blocks_read++;
- tape.insert(tape.end(),block);
- block_start=read_pointer+block->get_discarded_bytes();
- block_end=block_start+block->get_raw_size()-1;
- read_pointer=block_end+1;
-
- if (!spaced) fprintf(stderr,"\n");
- spaced=false;
- char buffer[200];
- snprintf(buffer,200,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
- blocks_read-1,
- block_start,
- block_end,
- block->get_raw_size());
- fprintf(stderr,buffer);
-
+ err_integrity=true;
+ read_ahead=false;
if (cfg_ignore_block_errors){
- fprintf(stderr,"Warning: Block integrity check failed!\n");
- warnings++;
+ message="Warning: Block integrity check failed!\n";
+ warning=true;
} else {
- fprintf(stderr,"Error: Block integrity check failed!\n");
- errors++;
+ message="Error: Block integrity check failed!\n";
+ error=true;
errcode=3;
- read_ahead=false;
}
- if(cfg_list_contents)
- dump_vector(block->get_description());
- fprintf(stderr,"\n");
- spaced=true;
}
catch(tape_block::checksum_error_exception &e){
block=e.get_block();
- blocks_read++;
- tape.insert(tape.end(),block);
- block_start=read_pointer+block->get_discarded_bytes();
- block_end=block_start+block->get_raw_size()-1;
- read_pointer=block_end+1;
-
-
- if (!spaced) fprintf(stderr,"\n");
- spaced=false;
- char buffer[200];
- snprintf(buffer,200,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
- blocks_read-1,
- block_start,
- block_end,
- block->get_raw_size());
- fprintf(stderr,buffer);
-
+ err_checksum=true;
if (cfg_ignore_checksum_errors){
- fprintf(stderr,"Warning: Block checksum wrong!\n");
- warnings++;
+ message="Warning: Block checksum wrong!\n";
+ warning=true;
} else {
- fprintf(stderr,"Error: Block checksum wrong!\n");
- errors++;
+ message="Error: Block checksum wrong!\n";
+ error=true;
read_ahead=false;
errcode=4;
}
- if(cfg_list_contents)
- dump_vector(block->get_description());
- fprintf(stderr,"\n");
- spaced=true;
}
-
- } // while (read_ahead)
-
- // Now we have our blocks, tell the user about that!
- if (!spaced) fprintf(stderr,"\n");
- spaced=false;
- char buffer[200];
- sprintf(buffer,"Bytes read:%i Blocks read:%i\nErrors:%i Warnings:%i\n",
- read_pointer,blocks_read,errors,warnings);
- if(cfg_output_info){
- write (out_fd,buffer,strlen(buffer));
- } else {
- fprintf(stderr,buffer);
- }
+ // Now let's check for block type
+ if ((!error)&&(!warning)&&!block->has_known_type()){
+ if (cfg_ignore_unknown_block_errors){
+ message="Warning: Unknown Block type!";
+ warning=true;
+ }else{
+ message="Error: Unknown Block type!";
+ error=true;
+ read_ahead=false;
+ errcode=5;
+ }
+ }
+
+ // Count block.
+ blocks_read++;
+ tape.insert(tape.end(),block);
+ block_start=read_pointer+block->get_discarded_bytes();
+ block_end=block_start+block->get_raw_size()-1;
+ read_pointer=block_end+1;
+
+ FILE * fp=stdwarn;
+ if (error) fp=stderr;
+
+ if (cfg_verbose||error||warning){
+ if (!spaced) fprintf(fp,"\n");
+ spaced=false;
+ fprintf(fp,"Block No.%03i: Start:0x%04x End:0x%04x Size:0x%02x\n",
+ blocks_read-1,
+ block_start,
+ block_end,
+ block->get_raw_size());
+ }
+
+ if (error) fprintf(stderr,message.c_str());
+ if (warning) fprintf(stdwarn,message.c_str());
+
+ if(cfg_list_contents){
+ dump_vector(block->get_description());
+ if (!error&&!warning) spaced=false;
+ }
- if (errors>0){
- fprintf(stderr,"Failed. (%i)\n",errcode);
- exit(errcode);
- }
-
+ if (error||warning||cfg_verbose){
+ fprintf(fp,"\n");
+ spaced=true;
+ }
+ if (error) errors++;
+ if (warning) warnings++;
+ } // while....
if (cfg_verbose){
- fprintf(stderr,"Data read successfully.\n");
+ close(in_fd);
+ fprintf(stderr,"Reading finished.\n");
+ fprintf(stderr,"Bytes read:%i, Blocks read:%i\n",read_pointer,blocks_read);
+ }
+} // read_tape()
+
+/******************************************************************************/
+
+void type_check(){
+ bool warning=false;
+ bool error=false;
+
+ for (unsigned int i=0; i<tape.size();i++){
+ bool spaced=false;
+ if (!tape[i]->has_known_type()){
+ FILE * fp;
+ if (cfg_ignore_unknown_block_errors){
+ fp=stdwarn;
+ warning=true;
+ } else {
+ fp=stderr;
+ error=true;
+ }
+ if (!spaced) {
+ spaced=false;fprintf(fp,"\n");
+ fprintf(fp,"Warning: Unknown Block type! Block No.%i\n",i);
+ dump_vector_fp(tape[i]->get_description(),fp);
+ fprintf(fp,"\n");
+ spaced=true;
+ }
+ if (!cfg_ignore_unknown_block_errors){
+ int errcode=5;
+ fprintf(stdwarn,"Failed. (%i)\n",errcode);
+ exit(errcode);
+ }
+ }
}
- close(in_fd);
-
-// switch(block->get_state()){ // switchy
-// case tape_block::TBS_EOF_LEGAL:
-// delete block;
-// if (!in_object){
-// fprintf(stderr,"File successfully read.\n");
-// } else {
-// if (cfg_ignore_object_integrity_errors){
-// fprintf(stderr,"Warning: Object integrity check failed!\n");
-// warnings++;
-// } else {
-// fprintf(stderr,"Error: Object integrity check failed!\n");
-// errors++;
-// errcode=6;
-// }
-// }
-// read_ahead=false;
-// break;
-// case tape_block::TBS_EOF_ILLEGAL:
-// break;
-// case tape_block::TBS_CHECKSUM:
-// break;
-// case tape_block::TBS_DEFAULT:
-// delete block;
-// fprintf(stderr,"TBS_DEFAULT encountered ->> SEVERE INTERNAL ERROR!\n");
-// errors++;
-// errcode=100;
-// read_ahead=false;
-// break;
-// case tape_block::TBS_IOERR:
-// case tape_block::TBS_OK:
-// tape.insert(tape.end(),block);
-// blocks_read++;
-
-// if (cfg_verbose){
-// char buffer[200];
-// snprintf(buffer,200,"Block No. %3i: Start(hex):%5x End(hex):%5x Size(hex):%3x\n",
-// blocks_read-1,
-// block_start,
-// block_end,
-// block->get_raw_size());
-// write (out_fd,buffer,strlen(buffer));
-// }
+} // type_check()
-// if(cfg_list_contents)
-// dump_vector(block->get_description());
-
-// if (block->get_type()==0x10){ // Unknown data block!
-// if (cfg_ignore_unknown_block_errors){
-// fprintf(stderr,"Warning: Unknown block type!\n");
-// warnings++;
-// }else {
-// fprintf(stderr,"Error: Unknown block type!\n");
-// errors++;
-// errcode=5;
-// read_ahead=false;
-// }
-// }
-
-// current_object.insert(current_object.end(),block);
-
-// if ((block->get_type()==data_block::TBT_EOT)
-// ||((block->get_type()==0)&&(block->get_subtype()==3))
-// ||((block->get_type()==4)||(block->get_type()==3))
-// ||((block->get_type()==0)&&(block->get_subtype()==014))){
-// in_object=false;
-// objects.insert(objects.end(),current_object);
-// current_object.clear();
-// } else {
-// in_object=true;
-// }
-
-// break;
-// } // switch
-// } // generate loop
+/******************************************************************************/
+/*!
+ *\brief The main routine.
+ */
+int main(int argc, char ** args){
-// }
+ // Do all the configuration stuff
+ do_config(argc,args);
+
+ // Output a version message if desired
+ if (cfg_version){
+ fprintf(stderr, ID_STRING, VERSION, BUILD_DATE, BUILD_STAMP);
+ exit(0);
+ }
+
+ // Assign warning output according to configuration
+ if (cfg_quiet) stdwarn=fopen("/dev/null","w");
+ else stdwarn=stderr;
+
+ read_tape(); // Process input to completion.
+ exit_on_error();
+
+
+
+ if (cfg_split_objects){
+ for (unsigned int i=0; i<tape.size();i++){
+ tape[i]->dump_to_fd(out_fd);
+ }
+ }
return 0;
return raw_data;
}
+/***************************************************************/
+/*!
+ *\brief Dump contents of the block to a file descriptor.
+ *
+ *\param fd A writable file descriptor.
+ *\return Always zero.
+ *\throw io_error_exception A write error occured.
+ */
+int tape_block::dump_to_fd(int fd){
+ int to_write=raw_size;
+ unsigned char * dump_ptr=raw_data;
+ int written;
+ while (to_write) {
+ written=write(fd,dump_ptr,to_write);
+ if (written < 0) throw io_error_exception();
+ to_write-=written;
+ dump_ptr+=written;
+ }
+ return 0;
+}
+
+/***************************************************************/
+/*!
+ *\brief Determine if the block marks the end of an object
+ *\retval true The block marks the end of an object.
+ *\retval false The block does not mark the end of an object.
+ *\note This is only a virtual method returning always false.
+ * Classes which can be the legal last block of an object
+ * will overwrite this method so that it returns true.
+ */
+bool tape_block::is_endblock(){
+ return false;
+}
+
+/***************************************************************/
+/*!
+ *\brief Get exported symbols.
+ *\return A vector containing any symbols exported in this block.
+ *\note This is only a virtual method returning always an empty
+ * vector. Classes describing appropriate data blocks
+ * will override this method.
+ */
+vector<string> tape_block::get_exported_symbols(){
+ vector<string> result;
+ return result;
+}
+
+/***************************************************************/
+/*!
+ *\brief Get called symbols.
+ *\return A vector containing any symbols called in this block.
+ *\note This is only a virtual method returning always an empty
+ * vector. Classes describing appropriate data blocks
+ * will override this method.
+ */
+vector<string> tape_block::get_called_symbols(){
+ vector<string> result;
+ return result;
+}
+
+/***************************************************************/
+/*!
+ *\brief Determine if the block has a known type.
+ *\return true if type and subtype are known.
+ *\return false if the block type is not one of the valid end
+ * nodes of the type tree.
+ */
+bool tape_block::has_known_type(){
+ return m_has_known_type;
+}
+
/***************************************************************/
/*!
*\brief Static factory method for tape blocks.
case tape_block::TBT_EOT:
n_eot_block=new eot_block(*n_tape_block);
delete n_tape_block;
+ n_eot_block->m_has_known_type=true;
return n_eot_block;
default: // Unknown block, a bad thing!
return n_tape_block;
}
if (n_data_block_0==0){ // So we must have found another one
delete n_data_block;
+ n_data_block_x->m_has_known_type=true;
return n_data_block_x;
}
case 001: n_data_block_0_x=new data_block_0_1(*n_data_block_0); break;
case 002: n_data_block_0_x=new data_block_0_2(*n_data_block_0); break;
case 003: n_data_block_0_x=new data_block_0_3(*n_data_block_0); break;
- case 004: n_data_block_0_x=new data_block_0_4(*n_data_block_0); break;
+ // case 004: n_data_block_0_x=new data_block_0_4(*n_data_block_0); break;
case 010: n_data_block_0_x=new data_block_0_10(*n_data_block_0); break;
case 014: n_data_block_0_x=new data_block_0_14(*n_data_block_0); break;
case 024: n_data_block_0_x=new data_block_0_24(*n_data_block_0); break;
return n_data_block_0;
}
delete n_data_block_0;
+ n_data_block_0_x->m_has_known_type=true;
return n_data_block_0_x;
}
break;
}
} while (buffer != (unsigned char) BLOCK_START_DELIMITER);
- discarded_bytes--; // Dont want to declare the start delimiter discarded!
+ discarded_bytes--; // Don't want to declare the start delimiter discarded!
raw_size=1; // But we want to account it here!
-
+
/* Now input the block data */
block_complete = 0;
+
+ raw_data[0]=buffer; // Put the start delimiter in!
+
do {
retval = read (fd, &buffer, 1);
/* sort in the new byte */
raw_size++;
// Need more memory??
- if (raw_size==poolsize){
+ if (raw_size>poolsize){
poolsize+=1024;
raw_data=(unsigned char*)realloc(raw_data,poolsize);
}
- raw_data[raw_size-2]=buffer;
+ raw_data[raw_size-1]=buffer;
/* Look for end ot block sequence */
switch(eob_needed){
*\retval 1 on error.
*/
int tape_block::init_words(){
- word_size=(raw_size-EOB_LENGTH)/3;
+ word_size=(raw_size-EOB_LENGTH-1)/3;
if (word_size<MINIMUM_DATA_BLOCK_WORDSIZE) return 1; // Block too short!
word_data=(unsigned short *)malloc(word_size*sizeof(unsigned short));
for (int pos=0; pos<word_size; pos++)
- word_data[pos]=combine466(raw_data+3*pos);
+ word_data[pos]=combine466(raw_data+1+3*pos);
return 0;
}
int get_raw_size();
int get_discarded_bytes();
unsigned char * get_raw_data();
-
+ virtual int dump_to_fd(int fd);
+ virtual bool is_endblock();
+ virtual vector<string> get_exported_symbols();
+ virtual vector<string> get_called_symbols();
+ virtual bool has_known_type();
+
static tape_block * gen_from_fd(int fd,
void(*input_start)(void *)=0,
void (*input_stop)(void *)=0,
protected: // members
int block_type; //!< Type of this block.
+ bool m_has_known_type; //!< Block is of a documented type.
int discarded_bytes; //!< Amount of bytes discarded before beginning.
unsigned char * raw_data; //!< Raw block data in bytes.
int raw_size; //!< Size of the raw data.
}
/*!
- *\brief Output a vector of strings to stderr.
+ *\brief Output a vector of strings.
*\arg strings A vector containing text.
+ *\arg fp A FILE pointer where to write to.
*\retval 0 The vector was empty.
*\retval 1 The vector contained text.
*/
-int dump_vector_err(vector<string> strings){
+int dump_vector_fp(vector<string> strings, FILE * fp){
int res=0;
for (vector<string>::iterator iter=strings.begin();iter<strings.end();iter++){
- char buffer[50000];
- snprintf(buffer,50000,"%s\n",(*iter).c_str());
- write (2,buffer,strlen(buffer));
+ fprintf(fp,"%s\n",(*iter).c_str());
res=1;
}
return res;
}
+
+/*!
+ *\brief add contents of one vector to another vector uniquely.
+ *\param target Reference to the target vector.
+ *\param source Reference to the vector whose contents are to be added
+ * to target.
+ */
+template<typename T>
+void merge_vector_unique(vector<T> &target, const vector<T> & source){
+ for (unsigned int isource=0; isource<source.size();isource++){
+ bool already_present=false;
+ for (int itarget=0;itarget<target.size();itarget++)
+ if (target[itarget]==source[isource]){
+ already_present=true;
+ break;
+ }
+ if (!already_present) target.insert(target.end().source[isource]);
+ }
+}
using namespace std;
extern int dump_vector(vector<string> strings);
-extern int dump_vector_err(vector<string> strings);
+extern int dump_vector_fp(vector<string> strings, FILE * fp);
+
+template<typename T>
+extern void merge_vector_unique(vector<T> &target, const vector<T> & source);
+
#endif