2000-04-26 18:26:31 +00:00
|
|
|
<!doctype linuxdoc system>
|
|
|
|
<!--
|
|
|
|
|
|
|
|
************************** begin comment *****************************
|
|
|
|
The following is the HOW-TO for programming in C++.
|
|
|
|
This document is in the SGML format. You must use sgml package to
|
|
|
|
process this document
|
|
|
|
************************* end of comment *****************************
|
|
|
|
|
|
|
|
-->
|
|
|
|
<!--
|
|
|
|
************************** SGML USER GUIDE *****************************
|
|
|
|
The SGML user guide on linux is located at /usr/doc/sgml-tools
|
|
|
|
Read the example.sgml and guide.html documents.
|
|
|
|
Usage:
|
|
|
|
HTML sgml2html foo (Do not give extension .sgml here!!)
|
|
|
|
Text sgml2txt foo.sgml
|
|
|
|
Latex sgml2latex foo.sgml
|
|
|
|
Postscript sgml2latex -language=english -o ps foo.sgml
|
|
|
|
DVI sgml2latex -d foo.sgml
|
|
|
|
Lyx sgml2lyx foo.sgml
|
|
|
|
Richtext sgml2rtf foo.sgml
|
|
|
|
gnuinfo sgml2info foo.sgml
|
|
|
|
man sgml2txt -man foo.sgml
|
|
|
|
SGML sgmlcheck foo.sgml
|
|
|
|
************************* end of comment *****************************
|
|
|
|
-->
|
|
|
|
|
|
|
|
<article>
|
|
|
|
|
|
|
|
<!-- Title information -->
|
|
|
|
|
|
|
|
<title>C++ Programming HOW-TO
|
|
|
|
<!-- chapt change
|
|
|
|
C++ Programming HOW-TO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<author>Al Dev (Alavoor Vasudevan)
|
|
|
|
<htmlurl url="mailto:alavoor@yahoo.com"
|
|
|
|
name="alavoor@yahoo.com">
|
2000-05-31 22:25:03 +00:00
|
|
|
<date>v9.0, 31 May 2000
|
2000-04-26 18:26:31 +00:00
|
|
|
<abstract>
|
|
|
|
This document discusses methods to avoid memory problems in C++ and
|
|
|
|
also will help you to program properly in C++ language.
|
|
|
|
The information in this document applies to all the operating sytems
|
|
|
|
that is - Linux, MS DOS, Apple Macintosh OS, Windows 95/NT,
|
|
|
|
OS/2, IBM OSes, VMS, Novell Netware, all flavors of
|
|
|
|
Unix like Solaris, HPUX, AIX, SCO, Sinix, BSD, etc.. and to
|
|
|
|
all other operating systems which support "C++" compiler (it
|
|
|
|
means almost all the operating systems on this planet!).
|
|
|
|
</abstract>
|
|
|
|
|
|
|
|
<!-- Table of contents -->
|
|
|
|
<toc>
|
|
|
|
|
|
|
|
<!-- Begin the document -->
|
|
|
|
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt>Introduction
|
|
|
|
-->
|
|
|
|
<sect>Introduction
|
|
|
|
<p>
|
|
|
|
C++ is the most popular language and will be used for a long time in the future
|
|
|
|
inspite of emergence of Java. C++ runs <bf>extremely fast</bf> and is
|
2000-05-31 22:25:03 +00:00
|
|
|
in fact <bf> 10 to 20 times FASTER than </bf> Java. Java runs very slow
|
|
|
|
because it is an byte-code-interpreted language running on top of "virtual engine".
|
|
|
|
Java runs faster with JIT compiler but is still slower than C++. And optimized
|
|
|
|
C++ program is
|
|
|
|
about <bf>3 to 4 times faster</bf> than Java
|
|
|
|
using the JIT (Just-In-Time) compiler!! The
|
2000-04-26 18:26:31 +00:00
|
|
|
memory management in Java is automated, so that programmers do not directly
|
|
|
|
deal with memory allocations. This document attempts
|
|
|
|
to automate the memory management in C++ to make it much more easy to use.
|
|
|
|
A neat feature of Java is that memory allocations are taken care of automatically.
|
|
|
|
This howto will enable "C++" to "compete/imitate" with Java language in memory management.
|
|
|
|
|
|
|
|
Because of manual memory allocations, debugging the C++ programs consumes a
|
|
|
|
major portion of time. The information
|
|
|
|
in this document will give you some better ideas and tips to reduce the debugging time.
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1>Problems facing the current C++ compilers
|
|
|
|
<p>
|
|
|
|
Since C++ is super-set of C, it got all the bad features of "C" language.
|
|
|
|
|
|
|
|
For example, in "C" programming - memory leaks, memory overflows are very common due
|
|
|
|
to usage of features like -
|
|
|
|
<code>
|
|
|
|
Datatype char * and char[]
|
|
|
|
String functions like strcpy, strcat, strncpy, strncat, etc..
|
|
|
|
Memory functions like malloc, realloc, strdup, etc..
|
|
|
|
</code>
|
|
|
|
|
|
|
|
The usage of <bf>char *</bf> and <bf>strcpy</bf> causes <it>horrible</it> memory
|
|
|
|
problems due to <it>"overflow"</it>,
|
2000-05-31 22:25:03 +00:00
|
|
|
<it>"fence past errors"</it>, <it>"step-on-others-toe"</it>
|
|
|
|
(hurting other variable's memory locations) or <it>"memory leaks"</it>.
|
2000-04-26 18:26:31 +00:00
|
|
|
The memory problems are extremely hard to debug and are
|
|
|
|
very time consuming to fix and trouble-shoot. Memory problems bring down
|
|
|
|
the productivity of programmers. This document helps in increasing the
|
|
|
|
productivity of programmers via different methods addressed to solve the
|
|
|
|
memory defects in "C++".
|
|
|
|
Memory related bugs are very tough to crack, and even experienced programmers
|
|
|
|
take several days, weeks or months to debug memory related problems. Many times memory
|
|
|
|
bugs will be "hiding" in the code for several months and can cause unexpected
|
|
|
|
program crashes!! The usage of
|
2000-05-31 22:25:03 +00:00
|
|
|
<bf>char *</bf> in C++
|
2000-04-26 18:26:31 +00:00
|
|
|
is costing USA and Japan $2 billion
|
|
|
|
every year in time lost in debugging and downtime of programs. If you use
|
|
|
|
<bf>char *</bf>
|
|
|
|
in C++ then it is a very costly affair especially if your programs have more
|
2000-05-31 22:25:03 +00:00
|
|
|
than 50,000 lines of code.
|
2000-04-26 18:26:31 +00:00
|
|
|
|
|
|
|
Hence, the following techniques are proposed to overcome the faults of "C"
|
|
|
|
language.
|
|
|
|
|
|
|
|
It is proposed that C++ compilers should prevent the programmers
|
|
|
|
from using the
|
|
|
|
<bf>"char *"</bf>
|
|
|
|
, <bf>"char[]"</bf> datatypes and
|
|
|
|
functions like <bf>strcpy</bf>, <bf>strcat</bf>,
|
|
|
|
<bf>strncpy</bf>, <bf>strncat</bf>.
|
|
|
|
The datatypes like char *, char[] and functions like strcpy, strcat
|
|
|
|
are <bf>evil</bf> and must be completetly <bf>BANNED</bf> from usage in C++!!
|
|
|
|
The
|
|
|
|
<bf>"char *"</bf>
|
2000-05-31 22:25:03 +00:00
|
|
|
is like <it>smallpox virus</it> and it must be eradicated from C++ world!!
|
|
|
|
If you want to use "char *" as in some system functions than you
|
|
|
|
should use "C" language. You would put
|
|
|
|
all your "C" programs in a seperate file and link to "C++" programs using
|
|
|
|
the <it>linkage-specification</it> statement <bf>extern "C" </bf> -
|
|
|
|
<code>
|
|
|
|
extern "C" {
|
|
|
|
#include <stdlib.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
comp();
|
|
|
|
some_c_function();
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
The <bf>extern "C"</bf> statement says that everything within the
|
|
|
|
brace-surrounded block - in this case, everything in the header file
|
|
|
|
and comp(), some_c_function() is compiled by a C compiler.
|
2000-04-26 18:26:31 +00:00
|
|
|
|
|
|
|
Instead of using char * and char[] all the C++ programmers MUST use the
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
which is given in this document and
|
|
|
|
<bf>'string class'</bf>
|
|
|
|
included in the STDLIB.
|
|
|
|
The
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
utilises the constructor and destructor to automate the memory management
|
|
|
|
and also provides many functions like <it>ltrim</it>, <it>substring</it>,
|
|
|
|
etc..
|
|
|
|
|
|
|
|
See also related
|
|
|
|
<bf>'string class'</bf>
|
|
|
|
in
|
|
|
|
the C++ compiler. The <bf>string class</bf> is part of the standard GNU C++
|
|
|
|
library and provides lot of string manipulation functions. The
|
|
|
|
<bf>'string class'</bf> and
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
can remove the need of <bf>char *</bf> datatype.
|
|
|
|
Also, C++ programmers must be encouraged to use 'new', 'delete'
|
|
|
|
features instead of using 'malloc' or 'free'.
|
|
|
|
|
|
|
|
The
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
does everything
|
|
|
|
that <bf>char *</bf> or <bf>char []</bf> does. It can
|
|
|
|
completely replace <bf>char</bf> datatype. Plus added
|
|
|
|
benefit is that programmers do not have to worry
|
|
|
|
about the memory problems and memory allocation at all!!
|
|
|
|
|
|
|
|
The GNU C++ compiler MUST drop off the support of <bf>char *, char[]</bf>
|
|
|
|
datatypes and in order to compile older programs using <bf>char</bf> datatype,
|
|
|
|
the compiler should provide a additional option called "-fchar-datatype" to g++ command.
|
|
|
|
Over the next 2 years all the C++ programs will use
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
and
|
|
|
|
<bf>'string class'</bf>
|
|
|
|
and there will be no char * and char[]. The compiler
|
|
|
|
should try to prevent bad programming practices!
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1>Which one "C", "C++" or Java ?
|
|
|
|
<p>
|
|
|
|
It is recommended you do programming in object-oriented "C++" for all your
|
|
|
|
application programming or general purpose programming. You can take full
|
|
|
|
advantage of object oriented facilities of C++. The C++ compiler is lot
|
|
|
|
more complex than "C" compiler and C++ programs may run bit slower than "C"
|
2000-05-31 22:25:03 +00:00
|
|
|
programs. But speed difference between "C" and "C++" is very minute - it
|
|
|
|
could be few milli-seconds which may have little impact
|
|
|
|
for real-time programming.
|
|
|
|
Since computer hardware is becoming cheaper and faster and memory
|
|
|
|
'RAM' is getting faster and cheaper, it is worth doing code in C++ rather than
|
|
|
|
"C" as time saved in clarity and re-usability of C++ code
|
|
|
|
offsets the slow speed.
|
|
|
|
Compiler optimizer options like -O or -O3 can speed up C++/C
|
|
|
|
which is not available in Java.
|
2000-04-26 18:26:31 +00:00
|
|
|
|
|
|
|
Nowadays, "C" language is primarily used for "systems programming" to develop
|
|
|
|
operating sytems, device drivers etc..
|
|
|
|
|
|
|
|
Java is platform independent language more suitable for developing GUI running
|
|
|
|
inside web-browsers (Java applets) but runs very slow. Prefer to
|
|
|
|
use web-server-side programming "Fast-CGI" with C++ and HTML, DHTML,
|
|
|
|
XML to get better performance. Hence, the golden rule is <it>"Web-server side programming
|
|
|
|
use C++ and web-client side (browser) programming use Java applets"</it>. The
|
|
|
|
reason is - the server-side OS is under your control and never changes and you
|
|
|
|
will never know what the client side web-browser OS is. It can be Windows 95/98/NT/2000
|
2000-05-31 22:25:03 +00:00
|
|
|
or Linux, Apple Mac, OS/2, Netware, Solaris etc..
|
|
|
|
|
|
|
|
The greatness of Java is that it can run "GUI Applets" on any OS platform!
|
|
|
|
Java was created to replace the Microsoft Windows 95/NT GUI clients.
|
|
|
|
In other words - "Java is the Windows-GUI system of next century". Java
|
|
|
|
is already embedded in web-browsers like Netscape, Hot Java, etc..
|
|
|
|
|
|
|
|
Hence, Java runs on "client" and C++ runs on servers!!
|
2000-04-26 18:26:31 +00:00
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Download mychar <label id = "Download mychar">
|
|
|
|
-->
|
|
|
|
<sect> Download mychar <label id = "Download mychar">
|
|
|
|
<p>
|
|
|
|
All the programs, examples are given in Appendix of this document.
|
|
|
|
You can download as a single tar zip, the mychar class, libraries
|
|
|
|
and example programs from
|
|
|
|
<itemize>
|
|
|
|
<item> Go here and click on C++Programming howto.tar.gz file <url url="http://www.aldev.8m.com">
|
|
|
|
<item> Mirror site : <url url="http://aldev.webjump.com">
|
|
|
|
</itemize>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Usage of mychar class
|
|
|
|
-->
|
|
|
|
<sect> Usage of mychar class
|
|
|
|
<p>
|
|
|
|
The
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
is a complete replacement for char and char * datatype.
|
|
|
|
You can use
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
just like char and get much more functionalities.
|
|
|
|
You should include the library 'libmychar.a' which you can build from the
|
|
|
|
makefile given in
|
|
|
|
<ref id ="Appendix H" name="Appendix H"> and copy the library to
|
|
|
|
/usr/lib directory where all the "C++" libraries are located. To use
|
|
|
|
the 'libmychar.a' compile your programs like -
|
|
|
|
<code>
|
|
|
|
g++ example.cpp -lmychar
|
|
|
|
</code>
|
|
|
|
See illustration sample code as given below -
|
|
|
|
<code>
|
|
|
|
mychar aa;
|
|
|
|
|
|
|
|
aa = " Washington DC is the capital of USA ";
|
|
|
|
|
|
|
|
// You can use aa.val like a 'char *' variable in programs !!
|
|
|
|
for (unsigned long tmpii = 0; tmpii < aa.length(); tmpii++)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "aa.val[%ld]=%c ", tmpii, aa.val[tmpii]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Using pointers on 'char *' val ...
|
|
|
|
for (; *aa.val != 0; aa.val++)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "aa.val=%c ", *aa.val);
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
A complete
|
|
|
|
example program "example_mychar.cpp" implementing the
|
|
|
|
mychar class is given in
|
|
|
|
<ref id ="Appendix A" name="Appendix A">
|
|
|
|
and mychar class is given in
|
|
|
|
<ref id ="Appendix B" name="Appendix B">.
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1> Operators
|
|
|
|
<p>
|
|
|
|
The
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
provides these operators :-
|
|
|
|
<itemize>
|
|
|
|
<item> Equal to <bf>==</bf>
|
|
|
|
<item> Not equal to <bf>!=</bf>
|
|
|
|
<item> Assignment <bf>=</bf>
|
|
|
|
<item> Add to itself and Assignment <bf>+=</bf>
|
|
|
|
<item> String concatenation or addition <bf>+</bf>
|
|
|
|
</itemize>
|
|
|
|
For example to use operators -
|
|
|
|
<code>
|
|
|
|
mychar aa;
|
|
|
|
mychar bb("Bill Clinton");
|
|
|
|
|
|
|
|
aa = "put some value string"; // assignment operator
|
|
|
|
aa += "add some more"; // Add to itself and assign operator
|
|
|
|
aa = "My name is" + " Alavoor Vasudevan "; // string cat operator
|
|
|
|
|
|
|
|
if (bb == "Bill Clinton") // boolean equal to operator
|
|
|
|
cout << "bb is eqaul to 'Bill Clinton' " << endl;
|
|
|
|
|
|
|
|
if (bb != "Al Gore") // boolean 'not equal' to operator
|
|
|
|
cout << "bb is not equal to 'Al Gore'" << endl;
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1> Functions
|
|
|
|
<p>
|
|
|
|
The
|
|
|
|
<bf>'mychar class'</bf>
|
|
|
|
provides these functions :-
|
|
|
|
<itemize>
|
|
|
|
|
|
|
|
<item> Current string length <bf>length()</bf>
|
|
|
|
<item> Left trim the string. Remove leading white-spaces - newlines, tabs <bf>ltrim()</bf>
|
|
|
|
<item> Right trim the string. Remove trailing white-spaces - newlines, tabs <bf>rtrim()</bf>
|
|
|
|
<item> Remove trailing and leading white-spaces <bf>trim()</bf>
|
|
|
|
<item> Remove trailing newlines <bf>chop()</bf>
|
|
|
|
<item> Change string to upper case <bf>to_upper()</bf>
|
|
|
|
<item> Change string to lower case <bf>to_lower()</bf>
|
|
|
|
<item> Truncate or round-off the float value <bf>roundf(float input_val, short precision)</bf>
|
|
|
|
<item> Truncate or round-off the double value <bf>roundd(double input_val, short precision)</bf>
|
|
|
|
<item> Find position, matching substr beginning
|
|
|
|
from start <bf>pos(char *substr, unsigned long start)</bf>
|
|
|
|
<item> Explodes the string and returns the list in the
|
|
|
|
list-head pointer explodeH <bf>explode(char *seperator)</bf>
|
|
|
|
<item> Implodes the strings in the list-head pointer explodeH and
|
|
|
|
returns the mychar variable <bf>implode(char *glue)</bf>
|
|
|
|
<item> Joins the strings in the list-head pointer explodeH and
|
|
|
|
returns the mychar variable <bf>join(char *glue)</bf>
|
|
|
|
<item> Repeat the input string n times <bf>repeat(char *input, unsigned int multiplier)</bf>
|
|
|
|
<item> Reverse the string characters <bf>reverse()</bf>
|
|
|
|
<item> Replace all occurences of string 'needle' with 'str' in
|
|
|
|
the haystack 'val' <bf>replace(char *needle, char *str)</bf>
|
|
|
|
<item> Translate certain chars <bf>str_tr(char *from, char *to)</bf>
|
|
|
|
<item> Center the text string <bf>center(int length, char padchar = ' ')</bf>
|
|
|
|
<item> Formats the original string by placing 'number' of 'padchar' characters
|
|
|
|
between each set of blank-delimited words. Leading and Trailing blanks
|
|
|
|
are always removed. If 'number' is omitted or is 0, then all spaces are
|
|
|
|
in the string are removed. The default number is 0 and
|
|
|
|
default padchar ' ' <bf>space(int number = 0, char padchar = ' ')</bf>
|
|
|
|
<item> The result is string comprised of all characters between
|
|
|
|
and including 'start' and 'end' <bf>xrange(char start, char end)</bf>
|
|
|
|
<item> Removes any characters contained in 'list'. The default character
|
|
|
|
for 'list' is a blank ' ' <bf>compress(char *list)</bf>
|
|
|
|
<item> Deletes a portion of string of 'length' characters from 'start' position.
|
|
|
|
If start is greater than the string length than string is
|
|
|
|
unchanged <bf>delstr(int start, int length)</bf>
|
|
|
|
<item> The 'newstr' in inserted into val beginning at 'start'. The 'newstr' will
|
|
|
|
be padded or truncated to 'length' characters. The default 'length' is
|
|
|
|
string length
|
|
|
|
of newstr <bf>insert(char *newstr, int start = 0, int length = 0, char padchar = ' ')</bf>
|
|
|
|
<item> The result is string of 'length' chars madeup of leftmost chars in val.
|
|
|
|
Quick way to left justify a string <bf>left(int length = 0, char padchar = ' ')</bf>
|
|
|
|
<item> The result is string of 'length' chars madeup of rightmost chars in val.
|
|
|
|
Quick way to right justify a string <bf>right(int length = 0, char padchar = ' ')</bf>
|
|
|
|
<item> The 'newstr' in overlayed into val beginning at 'start'. The 'newstr' will
|
|
|
|
be padded or truncated to 'length' characters. The default 'length' is
|
|
|
|
string length
|
|
|
|
of newstr <bf>overlay(char *newstr, int start = 0, int length = 0, char padchar = ' ')</bf>
|
|
|
|
<item> Sub-string, extract a portion of string <bf>substr(int start, int length = 0)</bf>
|
|
|
|
<item> matches first match of regx <bf>at(char *regx)</bf>
|
|
|
|
<item> Returns string before regx <bf>before(char *regx)</bf>
|
|
|
|
<item> Returns string after regx <bf>after(char *regx)</bf>
|
|
|
|
<item> Returns true if string is NULL value <bf>bool isnull()</bf>
|
|
|
|
<item> Resets the string to NULL <bf>clear()</bf>
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1> Miscellaneous Functions
|
|
|
|
<p>
|
|
|
|
Some miscellaneous mychar functions are given here, but <bf>DO NOT USE</bf> these,
|
|
|
|
and instead use operators like '+', '+=', '==' etc.. These are 'private' members of
|
|
|
|
the 'mychar' class.
|
|
|
|
<itemize>
|
|
|
|
<item> Copy string <bf>str_cpy(char *bb)</bf>
|
|
|
|
<item> Long integer converted to string <bf>str_cpy(unsigned long bb)</bf>
|
|
|
|
<item> Integer converted to string <bf>str_cpy(int bb)</bf>
|
|
|
|
<item> Float converted to string <bf>str_cpy(float bb)</bf>
|
|
|
|
<item> String concatenate a char * <bf>str_cat(char *bb)</bf>
|
|
|
|
<item> String concatenate a int <bf>str_cat(int bb)</bf>
|
|
|
|
<item> String concatenate a int <bf>str_cat(unsigned long bb)</bf>
|
|
|
|
<item> String concatenate a float <bf>str_cat(float bb)</bf>
|
|
|
|
<item> Is equal to mychar ? <bf>bool equalto(const mychar & rhs, bool type = false)</bf>
|
|
|
|
<item> Is equal to char* ? <bf>bool equalto(const char *rhs, bool type = false)</bf>
|
|
|
|
</itemize>
|
|
|
|
For example to convert integer to string do -
|
|
|
|
<code>
|
|
|
|
mychar aa;
|
|
|
|
|
|
|
|
aa = 34; // The '=' operator will convert int to string
|
|
|
|
cout << "The value of aa is : " << aa.val << endl;
|
|
|
|
|
|
|
|
aa = 234.878; // The '=' operator will convert float to string
|
|
|
|
cout << "The value of aa is : " << aa.val << endl;
|
|
|
|
|
|
|
|
aa = 34 + 234.878;
|
|
|
|
cout << "The value of aa is : " << aa.val << endl;
|
|
|
|
// The output aa will be '268.878'
|
|
|
|
|
|
|
|
// You must cast mychar to convert
|
|
|
|
aa = (mychar) 34 + " Honourable President Ronald Reagan " + 234.878;
|
|
|
|
cout << "The value of aa is : " << aa.val << endl;
|
|
|
|
// The output aa will be '34 Honourable President Ronald Reagan 234.878'
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> C++ Zap (Delete) command <label id="zap">
|
|
|
|
-->
|
|
|
|
<sect> C++ Zap (Delete) command <label id="zap">
|
|
|
|
<p>
|
|
|
|
The
|
|
|
|
<bf>delete</bf> and
|
|
|
|
<bf>new</bf>
|
|
|
|
commands in C++ are much better than the malloc and free functions of "C".
|
|
|
|
Consider using new and zap (delete command) instead of malloc and free
|
|
|
|
as much as possible.
|
|
|
|
|
|
|
|
To make
|
|
|
|
<bf>delete</bf>
|
|
|
|
command even more cleaner, make a Zap() command. Define
|
|
|
|
a zap() command like this:
|
|
|
|
<code>
|
|
|
|
/*
|
2000-04-28 18:00:14 +00:00
|
|
|
** Use do while to make it robust and bullet-proof macro.
|
|
|
|
** For example, if "do-while" is NOT used then results will be
|
|
|
|
** something else just as in -
|
|
|
|
** if (bbint == 4)
|
|
|
|
** aa = 0
|
|
|
|
** else
|
|
|
|
** zap(aptr); // Problem!! aptr will be always set to NULL
|
2000-04-26 18:26:31 +00:00
|
|
|
*/
|
2000-04-28 18:00:14 +00:00
|
|
|
|
|
|
|
#define zap(x) do { delete(x); x = NULL; } while (0)
|
2000-04-26 18:26:31 +00:00
|
|
|
</code>
|
|
|
|
|
2000-04-28 18:00:14 +00:00
|
|
|
The zap() command will delete the pointer and set it NULL.
|
|
|
|
This will ensure that even if multiple zap()'s are called on the
|
|
|
|
same deleted pointer then the
|
|
|
|
program will not crash. For example -
|
|
|
|
|
2000-04-26 18:26:31 +00:00
|
|
|
<code>
|
2000-04-28 18:00:14 +00:00
|
|
|
zap(pFirstname);
|
|
|
|
zap(pFirstname); // no core dumps !! Because pFirstname is NULL now
|
|
|
|
zap(pFirstname); // no core dumps !! Because pFirstname is NULL now
|
|
|
|
|
|
|
|
zap(pLastname);
|
|
|
|
zap(pJobDescription);
|
2000-04-26 18:26:31 +00:00
|
|
|
</code>
|
|
|
|
|
|
|
|
There is nothing magical about this, it just saves
|
2000-04-28 18:00:14 +00:00
|
|
|
repetative code, saves typing time and makes programs more readable. The
|
|
|
|
C++ programmers often forget to reset the deleted pointer
|
|
|
|
to NULL, and this causes annoying
|
|
|
|
problems causing core dumps and crashes. The zap() takes care of
|
|
|
|
this automatically.
|
|
|
|
Do not stick a typecast in the zap() command -- if something errors out on the
|
2000-04-26 18:26:31 +00:00
|
|
|
above zap() command it likely has another error somewhere.
|
|
|
|
|
|
|
|
Also
|
|
|
|
<ref id="my_malloc" name="my_malloc()">
|
|
|
|
, my_realloc() and my_free() should be used
|
|
|
|
instead of malloc(), realloc() and free(), as they
|
|
|
|
are much cleaner and have additional checks.
|
|
|
|
For an example, see the file "mychar.h" which is using
|
|
|
|
the
|
|
|
|
<ref id="my_malloc" name="my_malloc()">
|
|
|
|
and my_free() functions.
|
2000-05-31 22:25:03 +00:00
|
|
|
|
|
|
|
<bf>WARNING :</bf> Do not use free() to free memory allocated with 'new'
|
|
|
|
or 'delete' to free memory allocated with malloc. If you do, then
|
|
|
|
results will be unpredictable!!
|
2000-04-26 18:26:31 +00:00
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Pointers are problems <label id="pointers">
|
|
|
|
-->
|
|
|
|
<sect> Pointers are problems <label id="pointers">
|
|
|
|
<p>
|
2000-05-31 22:25:03 +00:00
|
|
|
Pointers are not required for general purpose programming. In modern
|
|
|
|
languages like Java there is no support for pointers!! Pointers make
|
|
|
|
the programs messy and programs using pointers are very hard to read.
|
|
|
|
|
|
|
|
Avoid using pointers as much as possible and use references. Pointers are really a
|
|
|
|
great pain. It is possible to write a application without using pointers.
|
|
|
|
|
2000-04-26 18:26:31 +00:00
|
|
|
A <bf>reference</bf> is an alias; when you create a reference, you initialize
|
|
|
|
it with the name of another object, the target. From the moment on, the reference
|
|
|
|
acts as an alternative name of the target, and anything you do to the reference
|
|
|
|
is really done to the target.
|
|
|
|
|
|
|
|
<bf>Syntax of References:</bf> Declare a reference by writing the type, followed by
|
|
|
|
the reference operator (&), followed by the reference name. References
|
|
|
|
<bf>MUST</bf> be initialized at the time of creation.
|
|
|
|
For example -
|
|
|
|
<code>
|
|
|
|
int weight;
|
|
|
|
int & rweight = weight;
|
|
|
|
|
|
|
|
DOG aa;
|
|
|
|
DOG & rDogRef = aa;
|
|
|
|
</code>
|
|
|
|
|
|
|
|
<it>Do's</it> of references -
|
|
|
|
<itemize>
|
|
|
|
<item>Do use references to create an alias to an object
|
|
|
|
<item>Do initialize all references
|
|
|
|
<item>Do use references for high efficiency and performance of program.
|
|
|
|
<item>Do use <bf>const</bf> to protect references and pointers whenever possible.
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
<it>Do not's</it> of references -
|
|
|
|
<itemize>
|
|
|
|
<item><bf>IMPORTANT: </bf>Don't use references to NULL objects !!!!
|
|
|
|
<item>Don't confuse the address of operator & with reference operator !! The references
|
|
|
|
are used in the declarations section (see Syntax of References above).
|
|
|
|
<item>Don't try to reassign a reference
|
|
|
|
<item>Don't use pointers if references will work
|
|
|
|
<item>Don't return a reference to a local object
|
|
|
|
<item>Don't pass by reference if the item referred to may go out of scope
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Usage of my_malloc and my_free <label id="my_malloc">
|
|
|
|
-->
|
|
|
|
<sect> Usage of my_malloc and my_free <label id="my_malloc">
|
|
|
|
<p>
|
|
|
|
Try to avoid using malloc and realloc as much as possible and use <bf>new</bf>
|
|
|
|
and <bf><ref id="zap" name="zap">(delete)</bf>. But sometimes you may need to
|
|
|
|
use the "C" style memory allocations in "C++". Use the functions
|
|
|
|
<bf>my_malloc()</bf> ,
|
|
|
|
<bf>my_realloc()</bf> and
|
|
|
|
<bf>my_free()</bf>.
|
|
|
|
These functions do proper allocations and initialisations and try to prevent
|
|
|
|
memory problems. Also these functions (in DEBUG mode) can keep track
|
|
|
|
of memory allocated and print total memory usage before and after the program
|
|
|
|
is run. This tells you if there are any memory leaks.
|
|
|
|
|
|
|
|
The my_malloc and my_realloc is defined as below. It allocates little more memory
|
|
|
|
(SAFE_MEM = 5) and initializes the space and if it cannot allocate it exits the
|
|
|
|
program. The 'call_check(), remove_ptr()' functions are active only when DEBUG is defined in
|
|
|
|
makefile and are assigned to
|
|
|
|
((void)0) i.e. NULL
|
|
|
|
for non-debug production release. They enable the total-memory used tracing.
|
|
|
|
|
|
|
|
<code>
|
|
|
|
void *local_my_malloc(size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
size_t tmpii = size + SAFE_MEM;
|
|
|
|
void *aa = NULL;
|
|
|
|
aa = (void *) malloc(tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(MALLOC, VOID_TYPE, fname, lineno);
|
|
|
|
memset(aa, 0, tmpii);
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *local_my_realloc(char *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpjj = 0;
|
|
|
|
if (aa) // aa != NULL
|
|
|
|
tmpjj = strlen(aa);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (char) * (tmpqq);
|
|
|
|
aa = (char *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
aa[tmpqq-1] = 0;
|
|
|
|
unsigned long kk = tmpjj;
|
|
|
|
if (tmpjj > tmpqq)
|
|
|
|
kk = tmpqq;
|
|
|
|
for ( ; kk < tmpqq; kk++)
|
|
|
|
aa[kk] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
See
|
|
|
|
<ref id ="Appendix D" name="my_malloc.cpp">.
|
|
|
|
and the header file
|
|
|
|
<ref id ="Appendix E" name="my_malloc.h">.
|
|
|
|
for full implementation of the my_malloc program.
|
|
|
|
|
|
|
|
An example on usage of my_malloc and my_free as below:
|
|
|
|
<code>
|
|
|
|
char *aa;
|
|
|
|
int *bb;
|
|
|
|
float *cc;
|
|
|
|
aa = (char *) my_malloc(sizeof(char)* 214);
|
|
|
|
bb = (int *) my_malloc(sizeof(int) * 10);
|
|
|
|
cc = (float *) my_malloc(sizeof(int) * 20);
|
|
|
|
|
|
|
|
aa = my_realloc(aa, sizeof(char) * 34);
|
|
|
|
bb = my_realloc(bb, sizeof(int) * 14);
|
|
|
|
cc = my_realloc(cc, sizeof(float) * 10);
|
|
|
|
</code>
|
|
|
|
Note that in my_realloc you do not need to cast the datatype as the
|
|
|
|
variable itself is passed and correct my_realloc is called which
|
|
|
|
returns the proper datatype pointer. The my_realloc has overloaded
|
|
|
|
functions for char*, int* and float*.
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Debug files
|
|
|
|
-->
|
|
|
|
<sect> Debug files
|
|
|
|
<p>
|
|
|
|
To debug any C++ or C programs include the file
|
|
|
|
<ref id="Appendix F" name="debug.h">
|
|
|
|
and in your 'Makefile' define DEBUG to turn on the traces from the debug.h functions.
|
2000-04-28 18:00:14 +00:00
|
|
|
When you remove the '-DDEBUG' then the debug function calls are set to
|
2000-04-26 18:26:31 +00:00
|
|
|
((void)0) i.e. NULL,
|
|
|
|
hence it has no impact on final production release version of project. You can generously
|
|
|
|
use the debug functions in your programs and it will not increase the size of production
|
|
|
|
executable.
|
|
|
|
|
|
|
|
See the file
|
|
|
|
<ref id="Appendix G" name="debug.cpp">
|
|
|
|
for implementation of debug routines.
|
|
|
|
And see the file
|
|
|
|
<ref id="Appendix D" name="my_malloc.cpp">
|
|
|
|
for sample which uses debug.h and debug functions.
|
|
|
|
|
|
|
|
See the sample
|
|
|
|
<ref id="Appendix H" name="Makefile">
|
|
|
|
.
|
|
|
|
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> C++ Online-Docs
|
|
|
|
-->
|
|
|
|
<sect> C++ Online-Docs
|
|
|
|
<p>
|
|
|
|
Visit the following C++ sites :-
|
|
|
|
<itemize>
|
|
|
|
<item>C++ Crash-proof site <url url="http://www.troubleshooters.com/codecorn/crashprf.htm">
|
|
|
|
<item>C++ Memory site<url url="http://www.troubleshooters.com/codecorn/memleak.htm">
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
Internet has vast amounts of documentation on C++. Visit the search engines
|
|
|
|
like Yahoo, Lycos, Infoseek, Excite. Type in the
|
|
|
|
keywords
|
|
|
|
<bf>'C++ tutorials'</bf>
|
|
|
|
<bf>'C++ references'</bf>
|
|
|
|
<bf>'C++ books'</bf>
|
|
|
|
. You can narrow down the search criteria by clicking on <it>Advanced</it>
|
|
|
|
search and select <it>search by exact phrase</it>
|
|
|
|
|
|
|
|
<itemize>
|
|
|
|
<item> <url url="http://www.yahoo.com">
|
|
|
|
<item> <url url="http://www.lycos.com">
|
|
|
|
<item> <url url="http://www.infoseek.com">
|
|
|
|
<item> <url url="http://www.excite.com">
|
|
|
|
<item> <url url="http://www.mamma.com">
|
|
|
|
</itemize>
|
|
|
|
<sect1> C++ Tutorials
|
|
|
|
<p>
|
|
|
|
There are many on-line tutorials available on internet. Type 'C++ tutorials'
|
|
|
|
in the search engine.
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1> C++ Coding Standards
|
|
|
|
<p>
|
|
|
|
Visit the C++ Coding Standards URLs
|
|
|
|
<itemize>
|
|
|
|
<item> C++ coding standard <url url="http://www.cs.umd.edu/users/cml/cstyle/CppCodingStandard.html">
|
|
|
|
<item> Coding standards from Possibility <url url="http://www.possibility.com/Cpp/CppCodingStandard.html">
|
|
|
|
<item> Coding standards from Ambysoft <url url="http://www.ambysoft.com/javaCodingStandards.html">
|
|
|
|
|
|
|
|
<item> Rules and recommendations <url url="http://www.cs.umd.edu/users/cml/cstyle/">
|
|
|
|
<item> Indent and annotate <url url="http://www.cs.umd.edu/users/cml/cstyle/indhill-annot.html">
|
|
|
|
<item> Elemental rules <url url="http://www.cs.umd.edu/users/cml/cstyle/Ellemtel-rules.html">
|
|
|
|
<item> C++ style doc <url url="http://www.cs.umd.edu/users/cml/cstyle/Wildfire-C++Style.html">
|
|
|
|
</itemize>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
<sect1> C++ Quick-Reference
|
|
|
|
<p>
|
|
|
|
Type 'C++ Reference' in the search engine.
|
|
|
|
<sect1> C++ Usenet Newsgroups
|
|
|
|
<p>
|
|
|
|
<itemize>
|
|
|
|
<item> C++ newsgroups : <url url="comp.lang.c++.announce">
|
|
|
|
<item> C++ newsgroups : <url url="comp.lang.c++.*">
|
|
|
|
</itemize>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt change> Memory Tools
|
|
|
|
-->
|
|
|
|
<sect> Memory Tools
|
|
|
|
<p>
|
|
|
|
Use the following memory debugging tools
|
|
|
|
<itemize>
|
|
|
|
<item> On linux contrib cdrom see mem_test*.rpm package
|
|
|
|
<item> On linux cdrom see ElectricFence*.rpm package
|
|
|
|
<item> Purify Tool from Rational Software Corp <url url="http://www.rational.com">
|
|
|
|
<item> Insure++ Tool from Parasoft Corp <url url="http://www.parasoft.com">
|
|
|
|
<item> Linux Tools at <url url="http://www.xnet.com/~blatura/linapp6.html#tools">
|
|
|
|
<item> Search the Internet engines like Yahoo, Lycos, Excite, Mamma.com
|
|
|
|
for keyword "Linux memory debugging tools".
|
|
|
|
</itemize>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt change> Related URLs
|
|
|
|
-->
|
|
|
|
<sect> Related URLs
|
|
|
|
<p>
|
|
|
|
Visit following locators which are related to C, C++ -
|
|
|
|
<itemize>
|
|
|
|
<item> Vim color text editor for C++, C <url url="http://metalab.unc.edu/LDP/HOWTO/Vim-HOWTO.html">
|
|
|
|
<item> C++ Beautifier HOWTO <url url="http://metalab.unc.edu/LDP/HOWTO/C-C++Beautifier-HOWTO.html">
|
|
|
|
<item> CVS HOWTO for C++ programs <url url="http://metalab.unc.edu/LDP/HOWTO/CVS-HOWTO.html">
|
|
|
|
<item> Linux goodies main site <url url="http://www.aldev.8m.com">
|
|
|
|
<item> Linux goodies mirror site <url url="http://aldev.webjump.com">
|
|
|
|
</itemize>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt change> Other Formats of this Document
|
|
|
|
-->
|
|
|
|
<sect> Other Formats of this Document
|
|
|
|
<p>
|
|
|
|
This document is published in 11 different formats namely - DVI, Postscript,
|
|
|
|
Latex, Adobe Acrobat PDF,
|
|
|
|
LyX, GNU-info, HTML, RTF(Rich Text Format), Plain-text, Unix man pages and SGML.
|
|
|
|
<itemize>
|
|
|
|
<item>
|
|
|
|
You can get this HOWTO document as a single file tar ball in HTML, DVI,
|
|
|
|
Postscript or SGML formats from -
|
|
|
|
<url url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/other-formats/">
|
|
|
|
or
|
|
|
|
<url url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/other-formats/">
|
|
|
|
|
|
|
|
<item>Plain text format is in: <url url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO">
|
|
|
|
or
|
|
|
|
<url url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO">
|
|
|
|
|
|
|
|
<item>Translations to other languages like French, German, Spanish,
|
|
|
|
Chinese, Japanese are in
|
|
|
|
<url url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO">
|
|
|
|
or <url url="ftp://metalab.unc.edu/pub/Linux/docs/HOWTO">
|
|
|
|
Any help from you to translate to other languages is welcome.
|
|
|
|
</itemize>
|
|
|
|
The document is written using a tool called "SGML tool" which can be got from -
|
|
|
|
<url url="http://www.xs4all.nl/~cg/sgmltools/">
|
|
|
|
Compiling the source you will get the following commands like
|
|
|
|
<itemize>
|
|
|
|
<item>sgml2html C++Programming-HOWTO.sgml (to generate html file)
|
|
|
|
<item>sgml2rtf C++Programming-HOWTO.sgml (to generate RTF file)
|
|
|
|
<item>sgml2latex C++Programming-HOWTO.sgml (to generate latex file)
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
This document is located at -
|
|
|
|
<itemize>
|
|
|
|
<item> <url url="http://metalab.unc.edu/LDP/HOWTO/C++Programming-HOWTO.html">
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
Also you can find this document at the following mirrors sites -
|
|
|
|
<itemize>
|
|
|
|
<item> <url url="http://www.caldera.com/LDP/HOWTO/C++Programming-HOWTO.html">
|
|
|
|
<item> <url url="http://www.WGS.com/LDP/HOWTO/C++Programming-HOWTO.html">
|
|
|
|
<item> <url url="http://www.cc.gatech.edu/linux/LDP/HOWTO/C++Programming-HOWTO.html">
|
|
|
|
<item> <url url="http://www.redhat.com/linux-info/ldp/HOWTO/C++Programming-HOWTO.html">
|
|
|
|
|
|
|
|
<item> Other mirror sites near you (network-address-wise) can be found at
|
|
|
|
<url url="http://metalab.unc.edu/LDP/hmirrors.html">
|
|
|
|
select a site and go to directory /LDP/HOWTO/C++Programming-HOWTO.html
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
|
|
|
|
In order to view the document in dvi format, use the xdvi program. The xdvi
|
|
|
|
program is located in tetex-xdvi*.rpm package in Redhat Linux which can be
|
|
|
|
located through ControlPanel | Applications | Publishing | TeX menu buttons.
|
|
|
|
<tscreen><verb>
|
|
|
|
To read dvi document give the command -
|
|
|
|
xdvi -geometry 80x90 howto.dvi
|
|
|
|
And resize the window with mouse. See man page on xdvi.
|
|
|
|
To navigate use Arrow keys, Page Up, Page Down keys, also
|
|
|
|
you can use 'f', 'd', 'u', 'c', 'l', 'r', 'p', 'n' letter
|
|
|
|
keys to move up, down, center, next page, previous page etc.
|
|
|
|
To turn off expert menu press 'x'.
|
|
|
|
</verb></tscreen>
|
|
|
|
You can read postscript file using the program 'gv' (ghostview) or
|
|
|
|
'ghostscript'.
|
|
|
|
The ghostscript program is in ghostscript*.rpm package and gv
|
|
|
|
program is in gv*.rpm package in Redhat Linux
|
|
|
|
which can be located through ControlPanel | Applications | Graphics menu
|
|
|
|
buttons. The gv program is much more user friendly than ghostscript.
|
|
|
|
Ghostscript and gv are also available on other platforms like OS/2,
|
|
|
|
Windows 95 and NT.
|
|
|
|
|
|
|
|
<itemize>
|
|
|
|
<item>Get ghostscript for Windows 95, OS/2, and for all OSes from <url url="http://www.cs.wisc.edu/~ghost">
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
<tscreen><verb>
|
|
|
|
To read postscript document give the command -
|
|
|
|
gv howto.ps
|
|
|
|
|
|
|
|
To use ghostscript give -
|
|
|
|
ghostscript howto.ps
|
|
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
You can read HTML format document using Netscape Navigator, Microsoft Internet
|
|
|
|
explorer, Redhat Baron Web browser or any other web browsers.
|
|
|
|
|
|
|
|
You can read the latex, LyX output using LyX a "X-Windows" front end to latex.
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Copyright
|
|
|
|
-->
|
|
|
|
<sect> Copyright
|
|
|
|
<p>
|
|
|
|
Copyright policy is GNU/GPL as per LDP (Linux Documentation project).
|
|
|
|
LDP is a GNU/GPL project.
|
|
|
|
Additional requests are - you must retain the author's name, email address
|
|
|
|
and this copyright notice on all the copies. If you make any changes
|
|
|
|
or additions to this document then you please
|
|
|
|
intimate all the authors of this document.
|
2000-05-31 22:25:03 +00:00
|
|
|
Brand names mentioned in this document are property of their respective
|
|
|
|
owners.
|
2000-04-26 18:26:31 +00:00
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix A example_mychar.cpp <label id="Appendix A">
|
|
|
|
-->
|
|
|
|
<sect> Appendix A example_mychar.cpp <label id="Appendix A">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
|
|
|
// And uncommnet the TEST_MYCHAR variable below -
|
|
|
|
|
|
|
|
#ifdef TEST_MYCHAR
|
|
|
|
|
|
|
|
#include <stdlib.h> // for putenv
|
|
|
|
#include "mychar.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
// A example program to demo usage of mychar
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
char p_name[1024];
|
|
|
|
sprintf(p_name, "PROGRAM_NAME=%s", argv[0]);
|
|
|
|
putenv(p_name);
|
|
|
|
print_total_memsize(); // in the beginning
|
|
|
|
mychar aa, bb;
|
|
|
|
|
|
|
|
//bb.str_cpy(" bbSTRing ");
|
|
|
|
bb = " bbSTRing ";
|
|
|
|
|
|
|
|
// Testing the + operator
|
|
|
|
// aa + " rhs "; // You will not get any output here !!!
|
|
|
|
// You must directly use in fprintf as in below line -
|
|
|
|
fprintf(stdout, "\n0) aa.val is :%sEOF\n", (aa + " my rhs " ).val);
|
|
|
|
|
|
|
|
// Testing the = operator
|
|
|
|
aa = " lhs " ;
|
|
|
|
fprintf(stdout, "0-1) With operator= aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
// Testing the + operator
|
|
|
|
// " lhs " + aa; // You will not get any output here !!!
|
|
|
|
// You must directly use in fprintf as in below line -
|
|
|
|
fprintf(stdout, "\n0) With lsh operator+, aa.val is :%sEOF\n", (" my lhs " + aa ).val);
|
|
|
|
|
|
|
|
//aa.str_cpy(bb.val);
|
|
|
|
aa = bb;
|
|
|
|
aa.to_upper();
|
|
|
|
fprintf(stdout, "1) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa.to_lower();
|
|
|
|
fprintf(stdout, "2) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa.ltrim();
|
|
|
|
fprintf(stdout, "3) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa.rtrim();
|
|
|
|
fprintf(stdout, "4) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa.trim();
|
|
|
|
fprintf(stdout, "5) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa = aa + " testing newlines \n\n\n\n";
|
|
|
|
aa.chop();
|
|
|
|
fprintf(stdout, "5-1) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa = aa + " rhs ";
|
|
|
|
fprintf(stdout, "6) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa = " lhs " + aa;
|
|
|
|
fprintf(stdout, "7) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
// Sample addition of numbers
|
|
|
|
//aa = (mychar) 9989 + "kkk" + 33 ;
|
|
|
|
aa = 9999;
|
|
|
|
fprintf(stdout, "7-1) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = bb;
|
|
|
|
aa = " lhs " + aa + " rhs " + " 9989 " + " 33 ";
|
|
|
|
fprintf(stdout, "8) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = " AA value ";
|
|
|
|
aa = bb + "alkja " + " 99djd " ;
|
|
|
|
fprintf(stdout, "9) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = " AA value ";
|
|
|
|
aa = (mychar) "alkja " + " 99djd " ;
|
|
|
|
fprintf(stdout, "10) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = " AA value ";
|
|
|
|
aa += (mychar) " al dev test kkk... " + " al2 slkj" + " al3333 ";
|
|
|
|
fprintf(stdout, "11) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = " AA value ";
|
|
|
|
aa = aa + " add aa " + aa + aa + aa + " 1111 " + " 2222 " + aa + aa + aa + " 3333 ";
|
|
|
|
fprintf(stdout, "12) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = "12345678";
|
|
|
|
aa.reverse();
|
|
|
|
fprintf(stdout, "13) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa = " AA value ";
|
|
|
|
aa = aa + " add aa " + aa + 1111 +" "+ 2222 + " " + 3.344 + aa;
|
|
|
|
fprintf(stdout, "14) aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa.roundd(123456.0123456789012345, 13);
|
|
|
|
fprintf(stdout, "15) double aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
aa.roundf(123456.0123456789, 13);
|
|
|
|
fprintf(stdout, "16) float aa.val is :%sEOF\n", aa.val);
|
|
|
|
|
|
|
|
// Test equal to operators
|
|
|
|
aa = " AA value ";
|
|
|
|
mychar cc(" AA value ");
|
|
|
|
if (aa == cc)
|
|
|
|
fprintf(stdout, "\naa=%s and cc=%s are equal!!\n", aa.val, cc.val);
|
|
|
|
else
|
|
|
|
fprintf(stdout, "\naa=%s and cc=%s are NOT equal!!\n", aa.val, cc.val);
|
|
|
|
cc = "CC";
|
|
|
|
if (aa == cc)
|
|
|
|
fprintf(stdout, "\naa=%s and cc=%s are equal!!\n", aa.val, cc.val);
|
|
|
|
else
|
|
|
|
fprintf(stdout, "\naa=%s and cc=%s are NOT equal!!\n", aa.val, cc.val);
|
|
|
|
if (aa == " AA value ")
|
|
|
|
fprintf(stdout, "\naa=%s and string are equal!!\n", aa.val);
|
|
|
|
else
|
|
|
|
fprintf(stdout, "\naa=%s and string are NOT equal!!\n", aa.val);
|
|
|
|
if (aa == " AA valuexxx ")
|
|
|
|
fprintf(stdout, "\naa=%s and string are equal!!\n", aa.val);
|
|
|
|
else
|
|
|
|
fprintf(stdout, "\naa=%s and string are NOT equal!!\n", aa.val);
|
|
|
|
|
|
|
|
// You can use aa.val like a 'char *' variable in programs !!
|
|
|
|
fprintf(stdout, "\n ");
|
|
|
|
for (unsigned long tmpii = 0; tmpii < aa.length(); tmpii++)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "aa.val[%ld]=%c ", tmpii, aa.val[tmpii]);
|
|
|
|
}
|
|
|
|
fprintf(stdout, "\n");
|
|
|
|
|
|
|
|
// Using pointers on 'char *' val ...
|
|
|
|
fprintf(stdout, "\n ");
|
|
|
|
for (; *aa.val != 0; aa.val++)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "aa.val=%c ", *aa.val);
|
|
|
|
}
|
|
|
|
fprintf(stdout, "\n");
|
|
|
|
|
|
|
|
print_total_memsize(); // in the end
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
#endif // TEST_MYCHAR
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix B mychar.h<label id="Appendix B">
|
|
|
|
-->
|
|
|
|
<sect> Appendix B mychar.h <label id="Appendix B">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
|
|
|
// To prevent memory leaks - a char class to manage character variables
|
|
|
|
// Always prefer to use mychar or string class
|
|
|
|
// instead of char[] or char *
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef __MYCHAR_H_
|
|
|
|
#define __MYCHAR_H_
|
|
|
|
|
|
|
|
//#include <iostream> // do not use iostream as program becomes bulky..
|
|
|
|
//#include <stdlib.h> // for free() amd malloc()
|
|
|
|
#include <string.h> // for strcpy()
|
|
|
|
#include <ctype.h> // for isspace()
|
|
|
|
#include <stdio.h> // for sprintf()
|
|
|
|
#include <list.h> // for sprintf()
|
|
|
|
#include <math.h> // for modf(), rint()
|
|
|
|
|
|
|
|
#include "my_malloc.h"
|
|
|
|
#include "debug.h" // debug_(name, value) debug2_(name, value, LOG_YES)
|
|
|
|
|
|
|
|
const short INITIAL_SIZE = 50;
|
|
|
|
const short NUMBER_LENGTH = 70;
|
|
|
|
|
|
|
|
// a small class with a VERY MINIMUM of functions and variables...
|
|
|
|
// This class to be kept small...
|
|
|
|
class mychar
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
mychar();
|
|
|
|
mychar(char bb[]); // needed by operator+
|
|
|
|
mychar(int bb); // needed by operator+
|
|
|
|
mychar(unsigned long bb); // needed by operator+
|
|
|
|
mychar(float bb); // needed by operator+
|
|
|
|
mychar(double bb); // needed by operator+
|
|
|
|
mychar(const mychar & rhs); // Copy Constructor needed by operator+
|
|
|
|
~mychar();
|
|
|
|
|
|
|
|
char *val;
|
|
|
|
|
|
|
|
unsigned long length() { return strlen(val); }
|
|
|
|
|
|
|
|
void ltrim();
|
|
|
|
void rtrim();
|
|
|
|
void trim();
|
|
|
|
void chop();
|
|
|
|
|
|
|
|
void to_upper();
|
|
|
|
void to_lower();
|
|
|
|
|
|
|
|
void roundf(float input_val, short precision);
|
|
|
|
void decompose_float(long *integral, long *fraction);
|
|
|
|
|
|
|
|
void roundd(double input_val, short precision);
|
|
|
|
void decompose_double(long *integral, long *fraction);
|
|
|
|
|
|
|
|
long pos(char substr[], unsigned long start);
|
|
|
|
|
|
|
|
void explode(char *seperator);
|
|
|
|
void implode(char *glue);
|
|
|
|
void join(char *glue);
|
|
|
|
void repeat(char *input, unsigned int multiplier);
|
|
|
|
void reverse();
|
|
|
|
void replace(char *needle, char *str);
|
|
|
|
void str_tr(char *from, char *to);
|
|
|
|
void center(int length, char padchar = ' ');
|
|
|
|
void space(int number = 0, char padchar = ' ');
|
|
|
|
void xrange(char start, char end);
|
|
|
|
void compress(char *list);
|
|
|
|
void delstr(int start, int length);
|
|
|
|
void insert(char *newstr, int start = 0, int length = 0, char padchar = ' ');
|
|
|
|
void left(int length = 0, char padchar = ' ');
|
|
|
|
void right(int length = 0, char padchar = ' ');
|
|
|
|
void overlay(char *newstr, int start = 0, int length = 0, char padchar = ' ');
|
|
|
|
mychar substr(int start, int length = 0);
|
|
|
|
|
|
|
|
mychar at(char *regx); // matches first match of regx
|
|
|
|
mychar before(char *regx); // returns string before regx
|
|
|
|
mychar after(char *regx); // returns string after regx
|
|
|
|
|
|
|
|
bool isnull();
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
// All Operators ...
|
|
|
|
mychar operator+ (const mychar & rhs);
|
|
|
|
friend mychar operator+ (const mychar & lhs, const mychar & rhs);
|
|
|
|
|
|
|
|
mychar& operator+= (const mychar & rhs); // using reference will be faster
|
|
|
|
mychar& operator= (const mychar & rhs); // using reference will be faster
|
|
|
|
bool operator== (const mychar & rhs); // using reference will be faster
|
|
|
|
bool operator== (const char *rhs);
|
|
|
|
bool operator!= (const mychar & rhs);
|
|
|
|
bool operator!= (const char *rhs);
|
|
|
|
|
|
|
|
static list<mychar> explodeH; // list head
|
|
|
|
|
|
|
|
private:
|
|
|
|
//static mychar *global_mychar; // for use in add operator
|
|
|
|
//inline void free_glob(mychar **aa);
|
|
|
|
void str_cpy(char bb[]);
|
|
|
|
void str_cpy(int bb); // itoa
|
|
|
|
void str_cpy(unsigned long bb);
|
|
|
|
void str_cpy(float bb); // itof
|
|
|
|
|
|
|
|
void str_cat(char bb[]);
|
|
|
|
void str_cat(int bb);
|
|
|
|
void str_cat(unsigned long bb);
|
|
|
|
void str_cat(float bb);
|
|
|
|
|
|
|
|
bool equalto(const mychar & rhs, bool type = false);
|
|
|
|
bool equalto(const char *rhs, bool type = false);
|
|
|
|
};
|
|
|
|
// Global variables are defined in mychar.cpp
|
|
|
|
|
|
|
|
#endif // __MYCHAR_H_
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix C mychar.cpp<label id="Appendix C">
|
|
|
|
-->
|
|
|
|
<sect> Appendix C mychar.cpp <label id="Appendix C">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
|
|
|
// Use string class or this class
|
|
|
|
//
|
|
|
|
// To prevent memory leaks - a char class to manage character variables
|
|
|
|
// Always prefer to use string class
|
|
|
|
// instead of char[] or char *
|
|
|
|
//
|
|
|
|
|
|
|
|
// To compile and test this program do -
|
|
|
|
// g++ mychar.cpp
|
|
|
|
|
|
|
|
#include "mychar.h"
|
|
|
|
|
|
|
|
// Global variables ....
|
|
|
|
//mychar *mychar::global_mychar = NULL; // global var
|
|
|
|
list<mychar> mychar::explodeH;
|
|
|
|
|
|
|
|
mychar::mychar()
|
|
|
|
{
|
|
|
|
debug_("In cstr()", "ok");
|
|
|
|
val = (char *) my_malloc(sizeof(char)* INITIAL_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar::mychar(char *bb)
|
|
|
|
{
|
|
|
|
unsigned long tmpii = strlen(bb);
|
|
|
|
val = (char *) my_malloc(sizeof(char)* tmpii);
|
|
|
|
strncpy(val, bb, tmpii);
|
|
|
|
val[tmpii] = '\0';
|
|
|
|
|
|
|
|
//debug_("In cstr(char *bb) bb", bb);
|
|
|
|
//debug_("In cstr(char *bb) val", val);
|
|
|
|
#ifdef DEBUG
|
|
|
|
//fprintf(stderr, "\nAddress of val=%x\n", & val);
|
|
|
|
//fprintf(stderr, "\nAddress of this-pointer=%x\n", this);
|
|
|
|
#endif // DEBUG
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar::mychar(int bb)
|
|
|
|
{
|
|
|
|
val = (char *) my_malloc(NUMBER_LENGTH); // integers 70 digits max
|
|
|
|
sprintf(val, "%d", bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar::mychar(unsigned long bb)
|
|
|
|
{
|
|
|
|
val = (char *) my_malloc(NUMBER_LENGTH); // long 70 digits max
|
|
|
|
sprintf(val, "%lu", bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar::mychar(float bb)
|
|
|
|
{
|
|
|
|
val = (char *) my_malloc(NUMBER_LENGTH); // float 70 digits max
|
|
|
|
sprintf(val, "%f", bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar::mychar(double bb)
|
|
|
|
{
|
|
|
|
val = (char *) my_malloc(NUMBER_LENGTH); // double 70 digits max
|
|
|
|
sprintf(val, "%f", bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy Constructor needed by operator +
|
|
|
|
mychar::mychar(const mychar & rhs)
|
|
|
|
{
|
|
|
|
// Do a deep-copy instead of compiler's default shallow copy copy-cstr
|
|
|
|
debug_("In copy-cstr()", "ok");
|
|
|
|
unsigned long tmpii = strlen(rhs.val);
|
|
|
|
val = (char *) my_malloc(sizeof(char)* tmpii);
|
|
|
|
strncpy(val, rhs.val, tmpii);
|
|
|
|
val[tmpii] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar::~mychar()
|
|
|
|
{
|
|
|
|
//debug_("In dstr val", val);
|
|
|
|
#ifdef DEBUG
|
|
|
|
//fprintf(stderr, "\nAddress of val=%x\n", & val);
|
|
|
|
//fprintf(stderr, "\nAddress of this-pointer=%x\n", this);
|
|
|
|
#endif // DEBUG
|
|
|
|
my_free(val);
|
|
|
|
//delete [] val;
|
|
|
|
val = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// MUST use pointer-to-pointer **aa, otherwise the argument
|
|
|
|
// is NOT freed !!
|
|
|
|
/*
|
|
|
|
inline void mychar::free_glob(mychar **aa)
|
|
|
|
{
|
|
|
|
debug_("called free_glob()", "ok" );
|
|
|
|
if (*aa != NULL) // (*aa != NULL)
|
|
|
|
{
|
|
|
|
debug_("*aa is not null", "ok");
|
|
|
|
delete *aa;
|
|
|
|
*aa = NULL;
|
|
|
|
}
|
|
|
|
//else
|
|
|
|
debug_("*aa is null", "ok");
|
|
|
|
|
|
|
|
//if (*aa == NULL)
|
|
|
|
debug_("*aa set to null", "ok");
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Explodes the string and returns the list in
|
|
|
|
// the list-head pointer explodeH
|
|
|
|
void mychar::explode(char *seperator)
|
|
|
|
{
|
|
|
|
char *aa = NULL, *bb = NULL;
|
|
|
|
aa = (char *) my_malloc(length());
|
|
|
|
for (bb = strtok(aa, seperator); bb != NULL; bb = strtok(NULL, seperator) )
|
|
|
|
{
|
|
|
|
mychar *tmp = new mychar(bb);
|
|
|
|
mychar::explodeH.insert(mychar::explodeH.end(), *tmp);
|
|
|
|
}
|
|
|
|
my_free(aa);
|
|
|
|
|
|
|
|
list<mychar>::iterator iter1; // see file include/g++/stl_list.h
|
|
|
|
debug_("Before checking explode..", "ok");
|
|
|
|
if (mychar::explodeH.empty() == true )
|
|
|
|
{
|
|
|
|
debug_("List is empty!!", "ok");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (iter1 = mychar::explodeH.begin(); iter1 != mychar::explodeH.end(); iter1++)
|
|
|
|
{
|
|
|
|
if (iter1 == NULL)
|
|
|
|
{
|
|
|
|
debug_("Iterator iter1 is NULL!!", "ok" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
debug_("(*iter1).val", (*iter1).val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implodes the strings in the list-head
|
|
|
|
// pointer explodeH and returns the mychar class
|
|
|
|
void mychar::implode(char *glue)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Joins the strings in the list-head
|
|
|
|
// pointer explodeH and returns the mychar class
|
|
|
|
void mychar::join(char *glue)
|
|
|
|
{
|
|
|
|
implode(glue);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Repeat the input string n times
|
|
|
|
void mychar::repeat(char *input, unsigned int multiplier)
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// repeat("1", 4) returns "1111"
|
|
|
|
if (!input) // input == NULL
|
|
|
|
{
|
|
|
|
val[0] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = (char *) my_malloc(strlen(input) * multiplier);
|
|
|
|
for (unsigned int tmpii = 0; tmpii < multiplier; tmpii++)
|
|
|
|
{
|
|
|
|
strcat(val, input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reverse the string
|
|
|
|
void mychar::reverse()
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// reverse() on "12345" returns "54321"
|
|
|
|
char aa;
|
|
|
|
unsigned long tot_len = length();
|
|
|
|
unsigned long midpoint = tot_len / 2;
|
|
|
|
for (unsigned long tmpjj = 0; tmpjj < midpoint; tmpjj++)
|
|
|
|
{
|
|
|
|
aa = val[tmpjj]; // temporary storage var
|
|
|
|
val[tmpjj] = val[tot_len - tmpjj - 1]; // swap the values
|
|
|
|
val[tot_len - tmpjj - 1] = aa; // swap the values
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace all occurences of string 'needle' with 'str' in the haystack 'val'
|
|
|
|
void mychar::replace(char *needle, char *str)
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// replace("AAA", "BB") on val = "some AAA and AAACC"
|
|
|
|
// reurns val = "some BB and BBCC"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Translate certain chars
|
|
|
|
void mychar::str_tr(char *from, char *to)
|
|
|
|
{
|
|
|
|
// For e.g ("abcd", "ABC") translates all occurences of each
|
|
|
|
// character in 'from' to corresponding character in 'to'
|
|
|
|
}
|
|
|
|
|
|
|
|
// Center the text
|
|
|
|
void center(int length, char padchar = ' ')
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// center(10, '*') on val="aa" returns "****aa****"
|
|
|
|
// center(10) on val="aa" returns " aa "
|
|
|
|
// The result is a string of 'length' characters with val centered in it.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Formats the original string by placing <number> of <padchar> characters
|
|
|
|
// between each set of blank-delimited words. Leading and Trailing blanks
|
|
|
|
// are always removed. If <number> is omitted or is 0, then all spaces are
|
|
|
|
// in the string are removed. The default number is 0 and
|
|
|
|
// default padchar ' '
|
|
|
|
void space(int number, char padchar = ' ')
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// space(3) on val = "I do not know"
|
|
|
|
// will return "I do not know"
|
|
|
|
// space(1, '_') on val = "A deep black space"
|
|
|
|
// will return "A_deep_black_space"
|
|
|
|
// space() on val = "I know this"
|
|
|
|
// will return "Iknowthis"
|
|
|
|
}
|
|
|
|
|
|
|
|
// The result is string comprised of all characters between
|
|
|
|
// and including <start> and <end>
|
|
|
|
void xrange(char start, char end)
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// xrange('a', 'j') returns val = "abcdefghij"
|
|
|
|
// xrange(1, 8) returns val = "12345678"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Removes any characters contained in <list>. The default character
|
|
|
|
// for <list> is a blank ' '
|
|
|
|
void compress(char *list)
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// compress("$,%") on val = "$1,934" returns "1934"
|
|
|
|
// compress() on val = "call me alavoor vasudevan" returns "callmealavoorvasudevan"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deletes a portion of string of <length> characters from <start> position.
|
2000-04-28 18:00:14 +00:00
|
|
|
// If start is greater than the string length then string is unchanged.
|
2000-04-26 18:26:31 +00:00
|
|
|
void delstr(int start, int length)
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// delstr(3,3) on val = 'pokemon' returns 'poon'
|
|
|
|
}
|
|
|
|
|
|
|
|
// The <newstr> in inserted into val beginning at <start>. The <newstr> will
|
|
|
|
// be padded or truncated to <length> characters. The default <length> is
|
|
|
|
// string length of newstr
|
|
|
|
void insert(char *newstr, int start = 0, int length = 0, char padchar = ' ')
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// insert("something new", 4, 20, '*') on val = "old thing"
|
|
|
|
// returns "old something new*******thing"
|
|
|
|
}
|
|
|
|
|
|
|
|
// The result is string of <length> chars madeup of leftmost chars in val.
|
|
|
|
// Quick way to left justify a string.
|
|
|
|
void left(int length = 0, char padchar = ' ')
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// left(10) on val = "Wig" returns "Wig "
|
|
|
|
// left(4) on val = "Wighat" returns "Wigh"
|
|
|
|
}
|
|
|
|
|
|
|
|
// The result is string of <length> chars madeup of rightmost chars in val.
|
|
|
|
// Quick way to right justify a string.
|
|
|
|
void right(int length = 0, char padchar = ' ')
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// right(10) on val = "never stop to saying" returns " to saying"
|
|
|
|
// right(4) on val = "Wighat" returns "ghat"
|
|
|
|
// right(6) on val = "4.50" returns " 4.50"
|
|
|
|
}
|
|
|
|
|
|
|
|
// The <newstr> in overlayed into val beginning at <start>. The <newstr> will
|
|
|
|
// be padded or truncated to <length> characters. The default <length> is
|
|
|
|
// string length of newstr
|
|
|
|
void overlay(char *newstr, int start = 0, int length = 0, char padchar = ' ')
|
|
|
|
{
|
|
|
|
// For example -
|
|
|
|
// overlay("12345678", 4, 10, '*') on val = "oldthing is very bad"
|
|
|
|
// returns "old12345678**ery bad"
|
|
|
|
}
|
|
|
|
|
|
|
|
// sub string
|
|
|
|
mychar mychar::substr(int start, int length = 0)
|
|
|
|
{
|
|
|
|
if (!length) // length == 0
|
|
|
|
return(mychar(& val[start-1]) );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mychar tmp = mychar(& val[start-1]);
|
|
|
|
tmp.val[length-1] = 0;
|
|
|
|
return(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If string is literrally equal to .. or not equal to
|
2000-04-28 18:00:14 +00:00
|
|
|
// If type is false then it is ==
|
2000-04-26 18:26:31 +00:00
|
|
|
bool mychar::equalto(const mychar & rhs, bool type = false)
|
|
|
|
{
|
|
|
|
if (type == false) // test for ==
|
|
|
|
{
|
|
|
|
if (strlen(rhs.val) == length())
|
|
|
|
{
|
|
|
|
if (!strncmp(rhs.val, val, length())) // == 0
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else // test for !=
|
|
|
|
{
|
|
|
|
if (strlen(rhs.val) != length())
|
|
|
|
{
|
|
|
|
if (!strncmp(rhs.val, val, length())) // == 0
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If string is literrally equal to .. or not equal to
|
2000-04-28 18:00:14 +00:00
|
|
|
// If type is false then it is ==
|
2000-04-26 18:26:31 +00:00
|
|
|
bool mychar::equalto(const char *rhs, bool type = false)
|
|
|
|
{
|
|
|
|
if (type == false) // test for ==
|
|
|
|
{
|
|
|
|
if (strlen(rhs) == length())
|
|
|
|
{
|
|
|
|
if (!strncmp(rhs, val, length())) // == 0
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else // test for !=
|
|
|
|
{
|
|
|
|
if (strlen(rhs) != length())
|
|
|
|
{
|
|
|
|
if (!strncmp(rhs, val, length())) // == 0
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// find position, matching substr beginning from start..
|
|
|
|
long mychar::pos(char *substr, unsigned long start)
|
|
|
|
{
|
|
|
|
char * tok;
|
|
|
|
long res = -1;
|
|
|
|
|
|
|
|
if ( !isnull() && (start < strlen(val) ) )
|
|
|
|
{
|
|
|
|
tok = strstr(val + start, substr);
|
|
|
|
if (tok == NULL)
|
|
|
|
res = -1;
|
|
|
|
else
|
|
|
|
res = (long) (tok - val);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mychar::isnull()
|
|
|
|
{
|
|
|
|
if (val[0] == '\0')
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (val == NULL)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::clear()
|
|
|
|
{
|
|
|
|
val = (char *) my_realloc(val, 10);
|
|
|
|
val[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove trailing new-lines
|
|
|
|
void mychar::chop()
|
|
|
|
{
|
|
|
|
unsigned long tmpii = strlen(val) - 1 ;
|
|
|
|
for (; tmpii >= 0; tmpii--)
|
|
|
|
{
|
|
|
|
if (val[tmpii] == '\n')
|
|
|
|
val[tmpii] = 0;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::ltrim()
|
|
|
|
{
|
|
|
|
// May cause problems in my_realloc since
|
|
|
|
// location of bb will be destroyed !!
|
|
|
|
char *bb = val;
|
|
|
|
|
|
|
|
if (bb == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (isspace(*bb))
|
|
|
|
bb++;
|
|
|
|
debug_("bb", bb);
|
|
|
|
|
|
|
|
if (bb != NULL && bb != val)
|
|
|
|
{
|
|
|
|
debug_("doing string copy", "done");
|
|
|
|
//str_cpy(bb); // causes problems in my_realloc and bb is getting destroyed!!
|
|
|
|
strcpy(val, bb); // strcpy is ok since val space is > bb space
|
|
|
|
}
|
|
|
|
else
|
|
|
|
debug_("Not doing string copy", "done");
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::rtrim()
|
|
|
|
{
|
|
|
|
for (long tmpii = strlen(val) - 1 ; tmpii >= 0; tmpii--)
|
|
|
|
{
|
|
|
|
if ( isspace(val[tmpii]) )
|
|
|
|
val[tmpii] = '\0';
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::trim()
|
|
|
|
{
|
|
|
|
rtrim();
|
|
|
|
ltrim();
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::to_lower()
|
|
|
|
{
|
|
|
|
for (long tmpii = strlen(val); tmpii >= 0; tmpii--)
|
|
|
|
{
|
|
|
|
val[tmpii] = tolower(val[tmpii]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use for rounding off fractions digits of floats
|
|
|
|
// Rounds-off floats with given precision and then
|
|
|
|
// stores the result into mychar's val field
|
|
|
|
// Also returns the result as a char *
|
|
|
|
void mychar::roundf(float input_val, short precision)
|
|
|
|
{
|
|
|
|
float integ_flt, deci_flt;
|
|
|
|
const short MAX_PREC = 4;
|
|
|
|
|
|
|
|
debug_("In roundf", "ok");
|
|
|
|
|
|
|
|
if (precision > MAX_PREC) // this is the max reliable precision
|
|
|
|
precision = MAX_PREC;
|
|
|
|
|
|
|
|
// get the integral and decimal parts of the float value..
|
|
|
|
deci_flt = modff(input_val, & integ_flt);
|
|
|
|
|
|
|
|
for (int tmpzz = 0; tmpzz < precision; tmpzz++)
|
|
|
|
{
|
|
|
|
debug_("deci_flt", deci_flt);
|
|
|
|
deci_flt *= 10;
|
|
|
|
}
|
|
|
|
debug_("deci_flt", deci_flt);
|
|
|
|
|
|
|
|
unsigned long deci_int = (unsigned long) ( rint(deci_flt) );
|
|
|
|
|
|
|
|
val = (char *) my_malloc(NUMBER_LENGTH); // float 70 digits max
|
|
|
|
|
|
|
|
if (deci_int > 999) // (MAX_PREC) digits
|
|
|
|
sprintf(val, "%lu.%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
if (deci_int > 99) // (MAX_PREC - 1) digits
|
|
|
|
sprintf(val, "%lu.0%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
if (deci_int > 9) // (MAX_PREC - 2) digits
|
|
|
|
sprintf(val, "%lu.00%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
sprintf(val, "%lu.00000%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::roundd(double input_val, short precision)
|
|
|
|
{
|
|
|
|
double integ_flt, deci_flt;
|
|
|
|
const short MAX_PREC = 6;
|
|
|
|
|
|
|
|
if (precision > MAX_PREC) // this is the max reliable precision
|
|
|
|
precision = MAX_PREC;
|
|
|
|
|
|
|
|
debug_("In roundd", "ok");
|
|
|
|
// get the integral and decimal parts of the double value..
|
|
|
|
deci_flt = modf(input_val, & integ_flt);
|
|
|
|
|
|
|
|
for (int tmpzz = 0; tmpzz < precision; tmpzz++)
|
|
|
|
{
|
|
|
|
debug_("deci_flt", deci_flt);
|
|
|
|
deci_flt *= 10;
|
|
|
|
}
|
|
|
|
debug_("deci_flt", deci_flt);
|
|
|
|
|
|
|
|
val = (char *) my_malloc(NUMBER_LENGTH); // double 70 digits max
|
|
|
|
|
|
|
|
unsigned long deci_int = (unsigned long) ( rint(deci_flt) );
|
|
|
|
|
|
|
|
if (deci_int > 99999) // (MAX_PREC) digits
|
|
|
|
sprintf(val, "%lu.%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
if (deci_int > 9999) // (MAX_PREC - 1) digits
|
|
|
|
sprintf(val, "%lu.0%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
if (deci_int > 999) // (MAX_PREC - 2) digits
|
|
|
|
sprintf(val, "%lu.00%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
if (deci_int > 99) // (MAX_PREC - 3) digits
|
|
|
|
sprintf(val, "%lu.000%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else
|
|
|
|
if (deci_int > 9) // (MAX_PREC - 4) digits
|
|
|
|
sprintf(val, "%lu.0000%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
else // (MAX_PREC - 5) digits
|
|
|
|
sprintf(val, "%lu.00000%lu", (unsigned long) integ_flt, deci_int);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::to_upper()
|
|
|
|
{
|
|
|
|
for (long tmpii = strlen(val); tmpii >= 0; tmpii--)
|
|
|
|
{
|
|
|
|
val[tmpii] = toupper(val[tmpii]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cpy(char bb[])
|
|
|
|
{
|
|
|
|
debug_("In str_cpy bb", bb);
|
|
|
|
if (bb == NULL)
|
|
|
|
{
|
|
|
|
val[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long tmpii = strlen(bb);
|
|
|
|
|
|
|
|
if (tmpii == 0)
|
|
|
|
{
|
|
|
|
val[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_("In str_cpy tmpii", tmpii);
|
|
|
|
debug_("In str_cpy val", val);
|
|
|
|
val = (char *) my_realloc(val, tmpii);
|
|
|
|
//val = new char [tmpii + SAFE_MEM_2];
|
|
|
|
debug_("In str_cpy bb", bb);
|
|
|
|
|
|
|
|
strncpy(val, bb, tmpii);
|
|
|
|
debug_("In str_cpy val", val);
|
|
|
|
val[tmpii] = '\0';
|
|
|
|
debug_("In str_cpy val", val);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cpy(int bb)
|
|
|
|
{
|
|
|
|
char tmpaa[100];
|
|
|
|
sprintf(tmpaa, "%d", bb);
|
|
|
|
str_cpy(tmpaa);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cpy(unsigned long bb)
|
|
|
|
{
|
|
|
|
char tmpaa[100];
|
|
|
|
sprintf(tmpaa, "%ld", bb);
|
|
|
|
str_cpy(tmpaa);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cpy(float bb)
|
|
|
|
{
|
|
|
|
char tmpaa[100];
|
|
|
|
sprintf(tmpaa, "%f", bb);
|
|
|
|
str_cpy(tmpaa);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cat(char bb[])
|
|
|
|
{
|
|
|
|
unsigned long tmpjj = strlen(bb), tmpii = strlen(val);
|
|
|
|
val = (char *) my_realloc(val, tmpii + tmpjj);
|
|
|
|
debug_("val in str_cat() ", val);
|
|
|
|
strncat(val, bb, tmpjj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cat(int bb)
|
|
|
|
{
|
|
|
|
char tmpaa[100];
|
|
|
|
sprintf(tmpaa, "%d", bb);
|
|
|
|
|
|
|
|
unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(val);
|
|
|
|
val = (char *) my_realloc(val, tmpii + tmpjj);
|
|
|
|
strncat(val, tmpaa, tmpjj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cat(unsigned long bb)
|
|
|
|
{
|
|
|
|
char tmpaa[100];
|
|
|
|
sprintf(tmpaa, "%ld", bb);
|
|
|
|
|
|
|
|
unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(val);
|
|
|
|
val = (char *) my_realloc(val, tmpii + tmpjj);
|
|
|
|
strncat(val, tmpaa, tmpjj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mychar::str_cat(float bb)
|
|
|
|
{
|
|
|
|
char tmpaa[100];
|
|
|
|
sprintf(tmpaa, "%f", bb);
|
|
|
|
|
|
|
|
unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(val);
|
|
|
|
val = (char *) my_realloc(val, tmpii + tmpjj);
|
|
|
|
strncat(val, tmpaa, tmpjj);
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar operator+ (const mychar & lhs, const mychar & rhs)
|
|
|
|
{
|
|
|
|
/*******************************************************/
|
|
|
|
// Note : For adding two char strings, first cast mychar
|
|
|
|
// as in -
|
|
|
|
//aa = (mychar) "alkja " + " 99djd " ;
|
|
|
|
/*******************************************************/
|
|
|
|
|
|
|
|
mychar tmp(lhs);
|
|
|
|
tmp.str_cat(rhs.val);
|
|
|
|
return(tmp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (mychar::global_mychar == NULL)
|
|
|
|
{
|
|
|
|
mychar::global_mychar = new mychar;
|
|
|
|
mychar::global_mychar->str_cpy(lhs.val);
|
|
|
|
mychar::global_mychar->str_cat(rhs.val);
|
|
|
|
//return *mychar::global_mychar;
|
|
|
|
return mychar(mychar::global_mychar->val);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
else
|
|
|
|
if (mychar::global_mychar1 == NULL)
|
|
|
|
{
|
|
|
|
debug_("1)global", "ok" );
|
|
|
|
mychar::global_mychar1 = new mychar;
|
|
|
|
mychar::global_mychar1->str_cpy(lhs.val);
|
|
|
|
mychar::global_mychar1->str_cat(rhs.val);
|
|
|
|
return *mychar::global_mychar1;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "\nError: cannot alloc global_mychar\n");
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
mychar *aa = new mychar;
|
|
|
|
aa->str_cpy(lhs.val);
|
|
|
|
aa->str_cat(rhs.val);
|
|
|
|
return *aa;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
mychar mychar::operator+ (const mychar & rhs)
|
|
|
|
{
|
|
|
|
mychar tmp(*this);
|
|
|
|
tmp.str_cat(rhs.val);
|
|
|
|
debug_("rhs.val in operator+", rhs.val );
|
|
|
|
debug_("tmp.val in operator+", tmp.val );
|
|
|
|
return (tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Using reference will be faster in = operator
|
|
|
|
mychar& mychar:: operator= ( const mychar& rhs )
|
|
|
|
{
|
|
|
|
if (& rhs == this)
|
|
|
|
{
|
|
|
|
debug_("Fatal Error: In operator(=). rhs is == to 'this pointer'!!", "ok" );
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->str_cpy(rhs.val);
|
|
|
|
debug_("rhs value", rhs.val );
|
|
|
|
|
|
|
|
// Free global vars memory
|
|
|
|
//free_glob(& mychar::global_mychar);
|
|
|
|
//if (mychar::global_mychar == NULL)
|
|
|
|
//fprintf(stderr, "\nglobal_mychar is freed!\n");
|
|
|
|
|
|
|
|
//return (mychar(*this));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Using reference will be faster in = operator
|
|
|
|
mychar& mychar::operator+= (const mychar & rhs)
|
|
|
|
{
|
|
|
|
/*******************************************************/
|
|
|
|
// Note : For adding two char strings, first cast mychar
|
|
|
|
// as in -
|
|
|
|
//aa += (mychar) "cccc" + "dddd";
|
|
|
|
/*******************************************************/
|
|
|
|
|
|
|
|
if (& rhs == this)
|
|
|
|
{
|
|
|
|
debug_("Fatal error: In operator+= rhs is equals 'this' ptr", "ok");
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
this->str_cat(rhs.val);
|
|
|
|
return *this;
|
|
|
|
//return (mychar(*this));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mychar::operator== (const mychar & rhs)
|
|
|
|
{
|
|
|
|
return(equalto(rhs.val));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mychar::operator== (const char *rhs)
|
|
|
|
{
|
|
|
|
return(equalto(rhs));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mychar::operator!= (const mychar & rhs)
|
|
|
|
{
|
|
|
|
return(equalto(rhs.val, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mychar::operator!= (const char *rhs)
|
|
|
|
{
|
|
|
|
return(equalto(rhs, true));
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix D my_malloc.cpp<label id="Appendix D">
|
|
|
|
-->
|
|
|
|
<sect> Appendix D my_malloc.cpp <label id="Appendix D">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
|
|
|
/*
|
|
|
|
** In your main() function put these lines -
|
|
|
|
char p_name[1024];
|
|
|
|
sprintf(p_name, "PROGRAM_NAME=%s", argv[0]);
|
|
|
|
putenv(p_name);
|
|
|
|
print_total_memsize(); // in the beginning
|
|
|
|
......
|
|
|
|
......
|
|
|
|
print_total_memsize(); // in the end
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <alloc.h> // for c++ -- malloc, alloc etc...
|
|
|
|
#include <stdlib.h> // malloc, alloc..
|
|
|
|
#include <time.h> // strftime, localtime, ...
|
|
|
|
#include <list.h> // strftime, localtime, ... see file include/g++/stl_list.h
|
|
|
|
//#include <debug.h> // debug_("a", a); debug2_("a", a, true);
|
|
|
|
|
|
|
|
#include "my_malloc.h"
|
|
|
|
|
|
|
|
const short SAFE_MEM = 10;
|
|
|
|
const short DATE_MAX_SIZE = 200;
|
|
|
|
|
|
|
|
const short MALLOC = 1;
|
|
|
|
const short REALLOC = 2;
|
|
|
|
|
|
|
|
const short VOID_TYPE = 1;
|
|
|
|
const short CHAR_TYPE = 2;
|
|
|
|
const short SHORT_TYPE = 3;
|
|
|
|
const short INT_TYPE = 4;
|
|
|
|
const short LONG_TYPE = 5;
|
|
|
|
const short FLOAT_TYPE = 6;
|
|
|
|
const short DOUBLE_TYPE = 7;
|
|
|
|
|
|
|
|
const char LOG_FILE[30] = "memory_error.log";
|
|
|
|
|
|
|
|
// Uncomment this line to debug total mem size allocated...
|
|
|
|
//#define DEBUG_MEM "debug_memory_sizes_allocated"
|
|
|
|
|
|
|
|
static void raise_error_exit(short mtype, short datatype, char fname[], int lineno);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
class MemCheck
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
MemCheck(void *aptr, size_t amem_size, char fname[], int lineno);
|
|
|
|
void *ptr;
|
|
|
|
size_t mem_size;
|
|
|
|
static list<MemCheck> mcH; // list head
|
|
|
|
static unsigned long total_memsize; // total memory allocated
|
|
|
|
};
|
|
|
|
|
|
|
|
// Global variables ....
|
|
|
|
list<MemCheck> MemCheck::mcH;
|
|
|
|
unsigned long MemCheck::total_memsize = 0;
|
|
|
|
|
|
|
|
MemCheck::MemCheck(void *aptr, size_t amem_size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
char func_name[100];
|
|
|
|
FILE *ferr = NULL;
|
|
|
|
sprintf(func_name, "MemCheck() - File: %s Line: %d", fname, lineno);
|
|
|
|
|
|
|
|
ferr = fopen(LOG_FILE, "a");
|
|
|
|
if (ferr == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
#ifdef DEBUG_MEM
|
|
|
|
exit(-1);
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search if the pointer already exists in the list...
|
|
|
|
bool does_exist = false;
|
|
|
|
list<MemCheck>::iterator iter1; // see file include/g++/stl_list.h
|
|
|
|
//fprintf(ferr, "\n%s Before checking.. !!\n", func_name);
|
|
|
|
if (MemCheck::mcH.empty() == true )
|
|
|
|
{
|
|
|
|
//fprintf(ferr, "\n%s List is empty!!\n", func_name);
|
|
|
|
}
|
|
|
|
for (iter1 = MemCheck::mcH.begin(); iter1 != MemCheck::mcH.end(); iter1++)
|
|
|
|
{
|
|
|
|
if (iter1 == NULL)
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n%s Iterator iter1 is NULL!!\n", func_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( ((*iter1).ptr) == aptr)
|
|
|
|
{
|
|
|
|
does_exist = true;
|
|
|
|
fprintf(ferr, "\n%s Already exists!!\n", func_name);
|
|
|
|
fprintf(ferr, "\n%s Fatal Error exiting now ....!!\n", func_name);
|
|
|
|
#ifdef DEBUG_MEM
|
|
|
|
exit(-1); //------------------------------------------------------------------>>>
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
// Now change the mem size to new values...
|
|
|
|
// For total size - Remove old size and add new size
|
|
|
|
//fprintf(ferr, "\n%s total_memsize = %lu\n", func_name, (*iter1).total_memsize);
|
|
|
|
//fprintf(ferr, "\n%s mem_size = %u\n", func_name, (*iter1).mem_size);
|
|
|
|
//fprintf(ferr, "\n%s amem_size = %u\n", func_name, amem_size);
|
|
|
|
(*iter1).total_memsize = (*iter1).total_memsize + amem_size;
|
|
|
|
if ((*iter1).total_memsize > 0 )
|
|
|
|
{
|
|
|
|
if ((*iter1).total_memsize >= (*iter1).mem_size )
|
|
|
|
(*iter1).total_memsize = (*iter1).total_memsize - (*iter1).mem_size;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n\n%s total_memsize is less than mem_size!!", func_name);
|
|
|
|
fprintf(ferr, "\n%s total_memsize = %lu", func_name, (*iter1).total_memsize);
|
|
|
|
fprintf(ferr, "\n%s mem_size = %u", func_name, (*iter1).mem_size);
|
|
|
|
fprintf(ferr, "\n%s amem_size = %u\n", func_name, amem_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(*iter1).mem_size = amem_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The pointer aptr does not exist in the list, so append it now...
|
|
|
|
if (does_exist == false)
|
|
|
|
{
|
|
|
|
//fprintf(ferr, "\n%s aptr Not found\n", func_name);
|
|
|
|
ptr = aptr;
|
|
|
|
mem_size = amem_size;
|
|
|
|
MemCheck::total_memsize += amem_size;
|
|
|
|
MemCheck::mcH.insert(MemCheck::mcH.end(), *this);
|
|
|
|
}
|
|
|
|
fclose(ferr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void call_check(void *aa, size_t tmpii, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
MemCheck bb(aa, tmpii, fname, lineno);
|
|
|
|
if (& bb); // a dummy statement to avoid compiler warning msg.
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void remove_ptr(void *aa, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
char func_name[100];
|
|
|
|
if (aa == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sprintf(func_name, "remove_ptr() - File: %s Line: %d", fname, lineno);
|
|
|
|
FILE *ferr = NULL;
|
|
|
|
ferr = fopen(LOG_FILE, "a");
|
|
|
|
if (ferr == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
#ifdef DEBUG_MEM
|
|
|
|
exit(-1);
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool does_exist = false;
|
|
|
|
if (MemCheck::mcH.empty() == true)
|
|
|
|
{
|
|
|
|
//fprintf(ferr, "\n%s List is empty!!\n", func_name);
|
|
|
|
//fclose(ferr);
|
|
|
|
//return;
|
|
|
|
}
|
|
|
|
list<MemCheck>::iterator iter1; // see file include/g++/stl_list.h
|
|
|
|
for (iter1 = MemCheck::mcH.begin(); iter1 != MemCheck::mcH.end(); iter1++)
|
|
|
|
{
|
|
|
|
if (iter1 == NULL)
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n%s Iterator iter1 is NULL!!\n", func_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( ((*iter1).ptr) == aa)
|
|
|
|
{
|
|
|
|
does_exist = true;
|
|
|
|
// Now change the mem size to new values...
|
|
|
|
// For total size - Remove old size
|
|
|
|
//fprintf(ferr, "\n%s total_memsize = %lu\n", func_name, (*iter1).total_memsize);
|
|
|
|
//fprintf(ferr, "\n%s mem_size = %u\n", func_name, (*iter1).mem_size);
|
|
|
|
if ((*iter1).total_memsize > 0 )
|
|
|
|
{
|
|
|
|
if ((*iter1).total_memsize >= (*iter1).mem_size )
|
|
|
|
(*iter1).total_memsize = (*iter1).total_memsize - (*iter1).mem_size;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n\n%s total_memsize is less than mem_size!!", func_name);
|
|
|
|
fprintf(ferr, "\n%s total_memsize = %lu", func_name, (*iter1).total_memsize);
|
|
|
|
fprintf(ferr, "\n%s mem_size = %u\n", func_name, (*iter1).mem_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MemCheck::mcH.erase(iter1);
|
|
|
|
break; // must break to avoid infinite looping
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (does_exist == false)
|
|
|
|
{
|
|
|
|
//fprintf(ferr, "\n%s Fatal Error: - You did not allocate memory!! \n", func_name);
|
|
|
|
//fprintf(ferr, "\n%s The value passed is %s\n", func_name, (char *) aa);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
//fprintf(ferr, "\n%s found\n", func_name);
|
|
|
|
fclose(ferr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void call_free_check(void *aa, char *fname, int lineno)
|
|
|
|
{
|
|
|
|
char func_name[100];
|
|
|
|
sprintf(func_name, "call_free_check() - File: %s Line: %d", fname, lineno);
|
|
|
|
|
|
|
|
FILE *ferr = NULL;
|
|
|
|
ferr = fopen(LOG_FILE, "a");
|
|
|
|
if (ferr == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
#ifdef DEBUG_MEM
|
|
|
|
exit(-1);
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool does_exist = false;
|
|
|
|
list<MemCheck>::iterator iter1; // see file include/g++/stl_list.h
|
|
|
|
for (iter1 = MemCheck::mcH.begin(); iter1 != MemCheck::mcH.end(); iter1++)
|
|
|
|
{
|
|
|
|
if (iter1 == NULL)
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n%s Iterator iter1 is NULL!!\n", func_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( ((*iter1).ptr) == aa)
|
|
|
|
{
|
|
|
|
does_exist = true;
|
|
|
|
//fprintf(ferr, "\n%s iter1.mem_size = %u\n", func_name, (*iter1).mem_size);
|
|
|
|
//fprintf(ferr, "\n%s Total memory allocated = %lu\n", func_name, (*iter1).total_memsize);
|
|
|
|
if ((*iter1).total_memsize > 0 )
|
|
|
|
{
|
|
|
|
if ((*iter1).total_memsize >= (*iter1).mem_size )
|
|
|
|
(*iter1).total_memsize = (*iter1).total_memsize - (*iter1).mem_size;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n\n%s total_memsize is less than mem_size!!", func_name);
|
|
|
|
fprintf(ferr, "\n%s total_memsize = %lu", func_name, (*iter1).total_memsize);
|
|
|
|
fprintf(ferr, "\n%s mem_size = %u", func_name, (*iter1).mem_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MemCheck::mcH.erase(iter1);
|
|
|
|
break; // must break to avoid infinite looping
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (does_exist == false)
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n%s Fatal Error: free() - You did not allocate memory!!\n",
|
|
|
|
func_name);
|
|
|
|
//fprintf(ferr, "\n%s The value passed is %s\n", func_name, (char *) aa);
|
|
|
|
fclose(ferr);
|
|
|
|
#ifdef DEBUG_MEM
|
|
|
|
exit(-1);
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//fprintf(ferr, "\n%s found\n", func_name);
|
|
|
|
}
|
|
|
|
fclose(ferr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void local_print_total_memsize(char *fname, int lineno)
|
|
|
|
{
|
|
|
|
char func_name[100];
|
|
|
|
sprintf(func_name, "local_print_total_memsize() - %s Line: %d", fname, lineno);
|
|
|
|
|
|
|
|
FILE *ferr = NULL;
|
|
|
|
ferr = fopen(LOG_FILE, "a");
|
|
|
|
if (ferr == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
fprintf(stderr, "\nWarning: Cannot open file %s\n", LOG_FILE);
|
|
|
|
#ifdef DEBUG_MEM
|
|
|
|
exit(-1);
|
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(ferr, "\n%s Total memory MemCheck::total_memsize = %lu\n", func_name, MemCheck::total_memsize);
|
|
|
|
fclose(ferr);
|
|
|
|
}
|
|
|
|
#else //------------> DEBUG
|
|
|
|
|
|
|
|
void local_print_total_memsize(char *fname, int lineno)
|
|
|
|
{
|
|
|
|
// This function is available whether debug or no-debug...
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
void local_my_free(void *aa, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
if (aa == NULL)
|
|
|
|
return;
|
|
|
|
call_free_check(aa, fname, lineno);
|
|
|
|
free(aa);
|
|
|
|
aa = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
void *local_my_malloc(size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
size_t tmpii = size + SAFE_MEM;
|
|
|
|
void *aa = NULL;
|
|
|
|
aa = (void *) malloc(tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(MALLOC, VOID_TYPE, fname, lineno);
|
|
|
|
memset(aa, 0, tmpii);
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
char *local_my_realloc(char *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpjj = 0;
|
|
|
|
if (aa) // aa != NULL
|
|
|
|
tmpjj = strlen(aa);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (char) * (tmpqq);
|
|
|
|
aa = (char *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
aa[tmpqq-1] = 0;
|
|
|
|
unsigned long kk = tmpjj;
|
|
|
|
if (tmpjj > tmpqq)
|
|
|
|
kk = tmpqq;
|
|
|
|
for ( ; kk < tmpqq; kk++)
|
|
|
|
aa[kk] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
short *local_my_realloc(short *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (short) * (tmpqq);
|
|
|
|
aa = (short *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
// Not for numbers!! aa[tmpqq-1] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
int *local_my_realloc(int *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (int) * (tmpqq);
|
|
|
|
aa = (int *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
// Not for numbers!! aa[tmpqq-1] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
long *local_my_realloc(long *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (long) * (tmpqq);
|
|
|
|
aa = (long *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
// Not for numbers!! aa[tmpqq-1] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
float *local_my_realloc(float *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (float) * (tmpqq);
|
|
|
|
aa = (float *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
// Not for numbers!! aa[tmpqq-1] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size_t is type-defed unsigned long
|
|
|
|
double *local_my_realloc(double *aa, size_t size, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
remove_ptr(aa, fname, lineno);
|
|
|
|
unsigned long tmpqq = size + SAFE_MEM;
|
|
|
|
size_t tmpii = sizeof (double) * (tmpqq);
|
|
|
|
aa = (double *) realloc(aa, tmpii);
|
|
|
|
if (aa == NULL)
|
|
|
|
raise_error_exit(REALLOC, CHAR_TYPE, fname, lineno);
|
|
|
|
// do not memset!! memset(aa, 0, tmpii);
|
|
|
|
// Not for numbers!! aa[tmpqq-1] = 0;
|
|
|
|
call_check(aa, tmpii, fname, lineno);
|
|
|
|
return aa;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void raise_error_exit(short mtype, short datatype, char fname[], int lineno)
|
|
|
|
{
|
|
|
|
if (mtype == MALLOC)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nFatal Error: malloc() failed!!");
|
|
|
|
fprintf(stderr, "\nFatal Error: malloc() failed!!");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (mtype == REALLOC)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nFatal Error: realloc() failed!!");
|
|
|
|
fprintf(stderr, "\nFatal Error: realloc() failed!!");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nFatal Error: mtype not supplied!!");
|
|
|
|
fprintf(stderr, "\nFatal Error: mtype not supplied!!");
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get current date-time and print time stamp in error file...
|
|
|
|
char date_str[DATE_MAX_SIZE + SAFE_MEM];
|
|
|
|
time_t tt;
|
|
|
|
tt = time(NULL);
|
|
|
|
struct tm *ct = NULL;
|
|
|
|
ct = localtime(& tt); // time() in secs since Epoch 1 Jan 1970
|
|
|
|
if (ct == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nWarning: Could not find the local time, localtime() failed\n");
|
|
|
|
fprintf(stderr, "\nWarning: Could not find the local time, localtime() failed\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strftime(date_str, DATE_MAX_SIZE , "%C", ct);
|
|
|
|
|
|
|
|
FILE *ferr = NULL;
|
|
|
|
char filename[100];
|
|
|
|
strcpy(filename, LOG_FILE);
|
|
|
|
ferr = fopen(filename, "a");
|
|
|
|
if (ferr == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stdout, "\nWarning: Cannot open file %s\n", filename);
|
|
|
|
fprintf(stderr, "\nWarning: Cannot open file %s\n", filename);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// **************************************************
|
|
|
|
// ******* Do putenv in the main() function *********
|
|
|
|
// char p_name[1024];
|
|
|
|
// sprintf(p_name, "PROGRAM_NAME=%s", argv[0]);
|
|
|
|
// putenv(p_name);
|
|
|
|
// **************************************************
|
|
|
|
char program_name[200+SAFE_MEM];
|
|
|
|
if (getenv("PROGRAM_NAME") == NULL)
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n%sWarning: You did not putenv() PROGRAM_NAME env variable in main() function\n",
|
|
|
|
date_str);
|
|
|
|
program_name[0] = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strncpy(program_name, getenv("PROGRAM_NAME"), 200);
|
|
|
|
|
|
|
|
if (mtype == MALLOC)
|
|
|
|
fprintf(ferr, "\n%s: %s - Fatal Error - my_malloc() failed.", date_str, program_name);
|
|
|
|
else
|
|
|
|
if (mtype == REALLOC)
|
|
|
|
{
|
|
|
|
fprintf(ferr, "\n%s: %s - Fatal Error - my_realloc() failed.", date_str, program_name);
|
|
|
|
char dtype[50];
|
|
|
|
switch(datatype)
|
|
|
|
{
|
|
|
|
case VOID_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
case CHAR_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
case SHORT_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
case INT_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
case LONG_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
case FLOAT_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
case DOUBLE_TYPE:
|
|
|
|
strcpy(dtype, "char*");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
strcpy(dtype, "none*");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fprintf(ferr, "\n%s %s - Fatal Error: %s realloc() failed!!", date_str, program_name, dtype);
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(ferr, "\n%s %s - Very severe error condition. Exiting application now....",
|
|
|
|
date_str, program_name);
|
|
|
|
fclose(ferr);
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix E my_malloc.h<label id="Appendix E">
|
|
|
|
-->
|
|
|
|
<sect> Appendix E my_malloc.h <label id="Appendix E">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
|
|
|
/*
|
|
|
|
** In your main() function put -
|
|
|
|
char p_name[1024];
|
|
|
|
sprintf(p_name, "PROGRAM_NAME=%s", argv[0]);
|
|
|
|
putenv(p_name);
|
|
|
|
print_total_memsize(); // in the beginning
|
|
|
|
......
|
|
|
|
......
|
|
|
|
print_total_memsize(); // in the end
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Use zap instead of delete as this will be very clean!!
|
|
|
|
** Use do while to make it robust and bullet-proof macro
|
|
|
|
*/
|
|
|
|
#define zap(x) do { if (x) { delete(x); x = 0; } } while (0)
|
|
|
|
|
|
|
|
void *local_my_malloc(size_t size, char fname[], int lineno);
|
|
|
|
|
|
|
|
char *local_my_realloc(char *aa, size_t size, char fname[], int lineno);
|
|
|
|
short *local_my_realloc(short *aa, size_t size, char fname[], int lineno);
|
|
|
|
void local_my_free(void *aa, char fname[], int lineno);
|
|
|
|
|
|
|
|
void local_print_total_memsize(char fname[], int lineno);
|
|
|
|
|
|
|
|
#define my_free(NM) (void) (local_my_free(NM, __FILE__, __LINE__))
|
|
|
|
#define my_malloc(SZ) (local_my_malloc(SZ, __FILE__, __LINE__))
|
|
|
|
#define my_realloc(NM, SZ) (local_my_realloc(NM, SZ, __FILE__, __LINE__))
|
|
|
|
#define print_total_memsize() (void) (local_print_total_memsize(__FILE__, __LINE__))
|
|
|
|
|
|
|
|
#ifdef DEBUG //------------> DEBUG
|
|
|
|
#else //------------> DEBUG
|
|
|
|
#define call_check(AA, BB, CC, DD) ((void) 0)
|
|
|
|
#define call_free_check(AA, BB, CC) ((void) 0)
|
|
|
|
#define remove_ptr(AA, CC, DD) ((void) 0)
|
|
|
|
#endif //------------> DEBUG
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix F debug.h<label id="Appendix F">
|
|
|
|
-->
|
|
|
|
<sect> Appendix F debug.h <label id="Appendix F">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
|
|
|
#define print_log(AA, BB, CC, DD, EE) ((void) 0)
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
|
|
//#include <assert.h> // assert() macro which is also used for debugging
|
|
|
|
|
|
|
|
const bool LOG_YES = true; // print output to log file
|
|
|
|
const bool LOG_NO = false; // Do not print output to log file
|
|
|
|
|
|
|
|
// Debugging code
|
|
|
|
// Use debug2_ to output result to a log file
|
|
|
|
|
|
|
|
#define debug_(NM, VL) (void) ( local_dbg(NM, VL, __FILE__, __LINE__) )
|
|
|
|
#define debug2_(NM, VL, LOG_FILE) (void) ( local_dbg(NM, VL, __FILE__, __LINE__, LOG_FILE) )
|
|
|
|
|
|
|
|
void local_dbg(char name[], char value[], char fname[], int lineno, bool logfile= false);
|
|
|
|
void local_dbg(char name[], string value, char fname[], int lineno, bool logfile= false);
|
|
|
|
void local_dbg(char name[], int value, char fname[], int lineno, bool logfile= false);
|
|
|
|
void local_dbg(char name[], unsigned long value, char fname[], int lineno, bool logfile= false);
|
|
|
|
void local_dbg(char name[], float value, char fname[], int lineno, bool logfile= false);
|
|
|
|
void local_dbg(char name[], double value, char fname[], int lineno, bool logfile= false);
|
|
|
|
|
|
|
|
#else //--------> else
|
|
|
|
|
|
|
|
#define debug_(NM, VL) ((void) 0)
|
|
|
|
#define debug2_(NM, VL, LOG_FILE) ((void) 0)
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix G debug.cpp <label id="Appendix G">
|
|
|
|
-->
|
|
|
|
<sect> Appendix G debug.cpp <label id="Appendix G">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
//*****************************************************************
|
|
|
|
// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
// that you include author's name and email on all copies
|
|
|
|
// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
//*****************************************************************
|
|
|
|
|
2000-04-28 18:00:14 +00:00
|
|
|
#ifdef DEBUG // ONLY if DEBUG is defined then these functions below are needed
|
2000-04-26 18:26:31 +00:00
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
//#include "log.h"
|
|
|
|
|
|
|
|
// Variable value[] can be char, string, int, unsigned long, float, etc...
|
|
|
|
|
|
|
|
void local_dbg(char name[], char value[], char fname[], int lineno, bool logfile) {
|
|
|
|
if (value == NULL)
|
|
|
|
return;
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %s\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], string value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %s\n", fname, lineno, name, value.c_str());
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value.c_str() << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], int value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %d\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], unsigned int value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %u\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], long value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %d\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], unsigned long value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %u\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], short value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %d\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], unsigned short value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %u\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], float value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %f\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
void local_dbg(char name[], double value, char fname[], int lineno, bool logfile) {
|
|
|
|
if (logfile == true)
|
|
|
|
print_log("\nDebug %s : Line: %d %s is = %f\n", fname, lineno, name, value);
|
|
|
|
else
|
|
|
|
cout << "\nDebug " << fname << ": Line: " << lineno << " " << name << " is = " << value << endl; }
|
|
|
|
|
|
|
|
// You add many more here - value can be a class, ENUM, datetime, etc...
|
|
|
|
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<chapt> Appendix H Makefile <label id="Appendix H">
|
|
|
|
-->
|
|
|
|
<sect> Appendix H Makefile <label id="Appendix H">
|
|
|
|
<p>
|
|
|
|
You can download all programs as a single tar.gz file from <ref id="Download mychar">.
|
|
|
|
To get this file, in the web-browser, save this file as 'Text' type.
|
|
|
|
<code>
|
|
|
|
#//*****************************************************************
|
|
|
|
#// Copyright policy is GNU/GPL but additional restriction is
|
|
|
|
#// that you include author's name and email on all copies
|
|
|
|
#// Author : Al Dev Email: alavoor@yahoo.com
|
|
|
|
#//*****************************************************************
|
|
|
|
|
|
|
|
.SUFFIXES: .pc .cpp .c .o
|
|
|
|
|
|
|
|
CC=gcc
|
|
|
|
CXX=g++
|
|
|
|
|
|
|
|
MAKEMAKE=mm
|
|
|
|
LIBRARY=libmychar.a
|
|
|
|
DEST=/home/myname/lib
|
|
|
|
|
|
|
|
# To build the library, and main test program uncomment line below :-
|
|
|
|
#MYCFLAGS=-O -DTEST_MYCHAR -Wall
|
|
|
|
|
|
|
|
# To test without debug trace uncomment line below:-
|
|
|
|
#MYCFLAGS=-g3 -DTEST_MYCHAR -Wall
|
|
|
|
|
|
|
|
# To enable 'full debug ' tracing uncomment line below:-
|
|
|
|
MYCFLAGS=-g3 -DDEBUG -DTEST_MYCHAR -Wall
|
|
|
|
|
|
|
|
#PURIFY=purify -best-effort
|
|
|
|
|
|
|
|
SRCS=my_malloc.cpp mychar.cpp debug.cpp example_mychar.cpp
|
|
|
|
HDR=my_malloc.h mychar.h debug.h
|
|
|
|
OBJS=my_malloc.o mychar.o debug.o example_mychar.o
|
|
|
|
EXE=mychar
|
|
|
|
|
|
|
|
# For generating makefile dependencies..
|
|
|
|
SHELL=/bin/sh
|
|
|
|
|
|
|
|
CPPFLAGS=$(MYCFLAGS) $(OS_DEFINES)
|
|
|
|
CFLAGS=$(MYCFLAGS) $(OS_DEFINES)
|
|
|
|
#
|
|
|
|
#MYLIBDIR=-L$(MY_DIR)/libmy
|
|
|
|
|
|
|
|
ALLLDFLAGS= $(LDFLAGS) $(MYLIBDIR)
|
|
|
|
|
|
|
|
COMMONLIBS=-lstdc++ -lm
|
|
|
|
LIBS=$(COMMONLIBS) $(MYLIBS)
|
|
|
|
|
|
|
|
all: $(LIBRARY) $(EXE)
|
|
|
|
|
|
|
|
$(MAKEMAKE):
|
|
|
|
@rm -f $(MAKEMAKE)
|
|
|
|
$(PURIFY) $(CXX) -M $(INCLUDE) $(CPPFLAGS) *.cpp > $(MAKEMAKE)
|
|
|
|
|
|
|
|
$(EXE): $(OBJS)
|
|
|
|
@echo "Creating a executable "
|
|
|
|
$(PURIFY) $(CC) -o $(EXE) $(OBJS) $(ALLLDFLAGS) $(LIBS)
|
|
|
|
|
|
|
|
$(LIBRARY): $(OBJS)
|
|
|
|
@echo "\n***********************************************"
|
|
|
|
@echo " Loading $(LIBRARY) ... to $(DEST)"
|
|
|
|
@echo "***********************************************"
|
|
|
|
@ar cru $(LIBRARY) $(OBJS)
|
|
|
|
@echo "\n "
|
|
|
|
|
|
|
|
.cpp.o: $(SRCS) $(HDR)
|
|
|
|
# @echo "Creating a object files from " $*.cpp " files "
|
|
|
|
$(PURIFY) $(CXX) -c $(INCLUDE) $(CPPFLAGS) $*.cpp
|
|
|
|
|
|
|
|
.c.o: $(SRCS) $(HDR)
|
|
|
|
# @echo "Creating a object files from " $*.c " files "
|
|
|
|
$(PURIFY) $(CC) -c $(INCLUDE) $(CFLAGS) $*.c
|
|
|
|
|
|
|
|
clean:
|
|
|
|
rm -f *.o *.log *~ *.log.old *.pid core err a.out lib*.a afiedt.buf
|
|
|
|
rm -f $(EXE)
|
|
|
|
rm -f $(MAKEMAKE)
|
|
|
|
|
|
|
|
#%.d: %.c
|
|
|
|
# @echo "Generating the dependency file *.d from *.c"
|
|
|
|
# $(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< | sed '\''s/$*.o/& $@/g'\'' > $@'
|
|
|
|
#%.d: %.cpp
|
|
|
|
# @echo "Generating the dependency file *.d from *.cpp"
|
|
|
|
# $(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< | sed '\''s/$*.o/& $@/g'\'' > $@'
|
|
|
|
|
|
|
|
# Must include all the c flags for -M option
|
|
|
|
#$(MAKEMAKE):
|
|
|
|
# @echo "Generating the dependency file *.d from *.cpp"
|
|
|
|
# $(CXX) -M $(INCLUDE) $(CPPFLAGS) *.cpp > $(MAKEMAKE)
|
|
|
|
|
|
|
|
include $(MAKEMAKE)
|
|
|
|
#include $(SRCS:.cpp=.d)
|
|
|
|
#include $(SRCS:.c=.d)
|
|
|
|
|
|
|
|
</code>
|
|
|
|
<!--
|
|
|
|
*******************************************
|
|
|
|
************ End of Section ***************
|
|
|
|
*******************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
</article>
|