473,320 Members | 1,691 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

How to log?

In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?
Jul 22 '05 #1
16 2038

"syncman" <hs***@hotmail.com> wrote in message news:cc**************************@posting.google.c om...
In C, I would always make a log() function instead of using printfs,

So, how do people log?


We have our own function called
LogPrintf
And our own stream called
LogOut

Based on the programmers inclination, he can either use either one.

Jul 22 '05 #2
syncman wrote:
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?


I've used a scheme like this one in the past. The actual logging class
was far more flexible than the one below but this example gives you an idea.

The interface is through the macro "LOG" and you pass it a logging level
and a title. The actual levels should be an enum but I just used an int
here for sake of simplicity (in a real system I would use mask).

LOG creates an object named "lout" which upon destruction will output
the log string.

i.e.

LOG( ERROR_LEVEL, "This is an error log" );

of

LOG( WARNING_LEVEL, "This is a warning" )
{
lout.attr( "oil_level" ) << oil_level << " is too low";
} // <<< message string is sent here

If logging is not enabled, no messages are created at all.

If you set the WARNING_LEVEL value to 0, the compiler will eliminate the
warning level logging code entirely.

THE one and only problem I've seen with this technique is that
occationally someone misses the ";" at the end and when logging is
turned on, the code works and when it is not it fails .... cute

I toyed with changing the interface to:

LOG( LOG_LEVEL, "Title" ) END_LOG

to eliminate this possibility of this kind of error but I'm still not
sure it's the best answer. Simplicity is better.

..... here is an example ....

#include <sstream>
#include <iostream>

#define LOG( LEVEL, TITLE ) \
if ( int x_level = (LEVEL) ) \
if ( Logger lout = x_level ) \
if ( lout.Title(TITLE) )
// end

struct LoggerContext
{
std::ostringstream m_oss;
int m_level;
mutable int m_count;

LoggerContext( int l_level )
: m_level( l_level ),
m_count( 1 )
{
}

};

struct Logger
{
LoggerContext * m_context;

static int min_level;

Logger( int l_level )
: m_context( l_level >= min_level ? new LoggerContext( l_level )
: 0 )
{
}

bool Title( const char * l_title )
{
m_context->m_oss << l_title << " : ";
return m_context;
}

template <typename T>
Logger & operator << ( const T & value )
{
m_context->m_oss << value;
return * this;
}

Logger & attr( const char * s_attr )
{
m_context->m_oss << " " << s_attr << " = ";
return * this;
}

~Logger()
{
if ( m_context )
{
-- m_context->m_count;
if ( m_context->m_count == 0 )
{
m_context->m_oss << "\n";
/// write log here
std::cout << m_context->m_oss.str();
delete m_context;
}
}
}

operator bool()
{
return m_context;
}

Logger( const Logger & l_rhs )
: m_context( l_rhs.getref() )
{
}

LoggerContext * getref() const
{
++ ( m_context->m_count );
return m_context;
}
};
int Logger::min_level = 2;
int main()
{
LOG( 3, "Thing 1" );

LOG( 4, "Thing 2" )
{
lout << "Really " << 33;
lout.attr( "Some value" ) << "54";
lout.attr( "Some other value" ) << 99.33;
}

LOG( 1, "Thing 3" )
{
lout << "Not really";
}

}

Jul 22 '05 #3
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
syncman wrote:
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?
I've used a scheme like this one in the past. The actual logging class
was far more flexible than the one below but this example gives you an

idea.
The interface is through the macro "LOG" and you pass it a logging level
and a title. The actual levels should be an enum but I just used an int
here for sake of simplicity (in a real system I would use mask).

LOG creates an object named "lout" which upon destruction will output
the log string.

i.e.

LOG( ERROR_LEVEL, "This is an error log" );

of

LOG( WARNING_LEVEL, "This is a warning" )
{
lout.attr( "oil_level" ) << oil_level << " is too low";
} // <<< message string is sent here

If logging is not enabled, no messages are created at all.

If you set the WARNING_LEVEL value to 0, the compiler will eliminate the
warning level logging code entirely.

THE one and only problem I've seen with this technique is that
occationally someone misses the ";" at the end and when logging is
turned on, the code works and when it is not it fails .... cute

I toyed with changing the interface to:

LOG( LOG_LEVEL, "Title" ) END_LOG

to eliminate this possibility of this kind of error but I'm still not
sure it's the best answer. Simplicity is better.

.... here is an example ....

#include <sstream>
#include <iostream>

#define LOG( LEVEL, TITLE ) \
if ( int x_level = (LEVEL) ) \
if ( Logger lout = x_level ) \
if ( lout.Title(TITLE) )
// end

struct LoggerContext
{
std::ostringstream m_oss;
int m_level;
mutable int m_count;

LoggerContext( int l_level )
: m_level( l_level ),
m_count( 1 )
{
}

};

struct Logger
{
LoggerContext * m_context;

static int min_level;

Logger( int l_level )
: m_context( l_level >= min_level ? new LoggerContext( l_level )
: 0 )
{
}

bool Title( const char * l_title )
{
m_context->m_oss << l_title << " : ";
return m_context;
}

template <typename T>
Logger & operator << ( const T & value )
{
m_context->m_oss << value;
return * this;
}

Logger & attr( const char * s_attr )
{
m_context->m_oss << " " << s_attr << " = ";
return * this;
}

~Logger()
{
if ( m_context )
{
-- m_context->m_count;
if ( m_context->m_count == 0 )
{
m_context->m_oss << "\n";
/// write log here
std::cout << m_context->m_oss.str();
delete m_context;
}
}
}

operator bool()
{
return m_context;
}

Logger( const Logger & l_rhs )
: m_context( l_rhs.getref() )
{
}

LoggerContext * getref() const
{
++ ( m_context->m_count );
return m_context;
}
};
int Logger::min_level = 2;
int main()
{
LOG( 3, "Thing 1" );

LOG( 4, "Thing 2" )
{
lout << "Really " << 33;
lout.attr( "Some value" ) << "54";
lout.attr( "Some other value" ) << 99.33;
}

LOG( 1, "Thing 3" )
{
lout << "Not really";
}

}


all you have to do is somehting like this:

// log.h
#ifdef LOG_ON
#define LOGNAME "debuglog.txt"
#define LOG( _S_) { lstream << _S_; }
extern std::ofstream lstream;
#else
#define LOG( _S_)
#endif

//////////////////
// log.cpp
#include "log.h"
#ifdef LOG_ON
#include <fstream>
std::ofstream lstream( LOGNAME );
#endif
// somefile.cpp
#include "log.h"
void func( int n )
{
LOG( "func called with " << n << std::endl );
}
all you have to do to turn logging on/ off is define ( or not, to turn off
logging ) LOG_ON

-Chris
Jul 22 '05 #4
"syncman" <hs***@hotmail.com> wrote in message
news:cc**************************@posting.google.c om...
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?


Here's an idea in C that makes use of a slightly sneaky preprocessor
feature. No doubt could be made a lot better for C++.

#include <stdio.h>
#include <stdarg.h>

#if defined(DEBUG)
#define TRACE(X) tracefunc X
#else
#define TRACE (void)
#endif

#if defined(DEBUG)
static void tracefunc(char *format, ...)
{
va_list marker;
static FILE *fp = NULL;

if (!fp)
{
fp = fopen("tracef.trc", "w+t"); // open
}

if (fp)
{
va_start(marker, format);
vfprintf(fp, format, marker);
va_end(marker);
fputc('\n', fp);
fflush(fp);
}
}
#endif

void main(void)
{
int a = 1;
char *b = "BBBB";

TRACE(("a=%d, b=%s", a, b));
TRACE(("b=%s, a=%d", b, a));
}
Jul 22 '05 #5
Chrisw wrote:
....

all you have to do is somehting like this:

// log.h
#ifdef LOG_ON
#define LOGNAME "debuglog.txt"
#define LOG( _S_) { lstream << _S_; }
extern std::ofstream lstream;
#else
#define LOG( _S_)
#endif

//////////////////
// log.cpp
#include "log.h"
#ifdef LOG_ON
#include <fstream>
std::ofstream lstream( LOGNAME );
#endif
// somefile.cpp
#include "log.h"
void func( int n )
{
LOG( "func called with " << n << std::endl );
}
all you have to do to turn logging on/ off is define ( or not, to turn off
logging ) LOG_ON


That's neat but:

a) I want all the code compiled all the time - this reduces errors from
conditionally compiled code. You could fix that here by placing an "if"
around the {}.

b) Logging can become intermixed if the logging itself causes logging to
be used. This also happens when multiple threads are used. I suspect
you could easily fix the macro to do that too.

c) Often what you need to log is more complex than just a message with
fixed parameters

LOG( INFORM_LEVEL, "Attribute dump" )
{
for ( attr_iter = attrs.begin(); ....
lout.attr( *attr.name ) << *attr.value ;
etc...

You could do somthing like:

LOG(
"Log title";
for ( int i = 0; i < 10; i ++ ) {
lstream << i;
}
)

However, now you can't use the operator ,() because the
preprocessor won't know what you mean.

Jul 22 '05 #6
[Snipped]
#include <stdio.h>
#include <stdarg.h>

#if defined(DEBUG)
#define TRACE(X) tracefunc X
#else
#define TRACE (void)
Why not #define TRACE(X) to nothing, why "(void)"?

#define TRACE(X)

--The Directive
#endif

#if defined(DEBUG)
static void tracefunc(char *format, ...)
{
va_list marker;
static FILE *fp = NULL;

if (!fp)
{
fp = fopen("tracef.trc", "w+t"); // open
}

if (fp)
{
va_start(marker, format);
vfprintf(fp, format, marker);
va_end(marker);
fputc('\n', fp);
fflush(fp);
}
}
#endif

void main(void)
{
int a = 1;
char *b = "BBBB";

TRACE(("a=%d, b=%s", a, b));
TRACE(("b=%s, a=%d", b, a));
}

Jul 22 '05 #7
Jarmo wrote:
"syncman" <hs***@hotmail.com> wrote in message
news:cc**************************@posting.google.c om...
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?

Here's an idea in C that makes use of a slightly sneaky preprocessor
feature. No doubt could be made a lot better for C++.

#include <stdio.h>
#include <stdarg.h>

#if defined(DEBUG)
#define TRACE(X) tracefunc X
#else
#define TRACE (void)
#endif


One of *my* biggest issues with conditional complication is that
compiling code conditionally often introduces undetected compilation errors.

#if defined(DEBUG)
#define DOING_DEBUG true
#else
#define DOING_DEBUG false
#endif

#define TRACE(X) if (DOING_DEBUG) { tracefunc X; }

I'd also like to be able to change the behaviour at run time and have
different "levels" of debugging .... but that's another story.

#if defined(DEBUG)
static void tracefunc(char *format, ...)
{
va_list marker;
static FILE *fp = NULL;

if (!fp)
{
fp = fopen("tracef.trc", "w+t"); // open
}

if (fp)
{
va_start(marker, format);
vfprintf(fp, format, marker);
va_end(marker);
fputc('\n', fp);
fflush(fp);
}
}
#endif

void main(void)
{
int a = 1;
char *b = "BBBB";

TRACE(("a=%d, b=%s", a, b));
TRACE(("b=%s, a=%d", b, a));
}


Jul 22 '05 #8
There is a very powerful logging facility called log4cplus. It is a
logging framework for C++ very similar to log4j (for Java, of course).

It allows as simple or as complex logging as you want, and you can set
the logging level dynamically.

I suggest you give that a try, as it might be useful to reuse this
framework instead of having to always write your own custom logging
facilities.

Jorge L

syncman wrote:
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?

Jul 22 '05 #9
"The Directive" <th***********@hotmail.com> wrote in message
news:84*************************@posting.google.co m...
[Snipped]
#include <stdio.h>
#include <stdarg.h>

#if defined(DEBUG)
#define TRACE(X) tracefunc X
#else
#define TRACE (void)


Why not #define TRACE(X) to nothing, why "(void)"?


Good question. If I recall, it was intended to eliminate compiler warnings
on some cranky, old compilers.
Jul 22 '05 #10
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
Jarmo wrote:
"syncman" <hs***@hotmail.com> wrote in message
news:cc**************************@posting.google.c om...


One of *my* biggest issues with conditional complication is that
compiling code conditionally often introduces undetected compilation

errors.

I'm not sure how a compilation error could be undetected, or do you mean a
programming error? Obviously, for performance and occupancy reasons, it's
very unusual for production code to include tracing so you do need some way
to build two versions (release & debug) from the same code.
Jul 22 '05 #11
Jarmo wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
Jarmo wrote:
"syncman" <hs***@hotmail.com> wrote in message
news:cc**************************@posting.googl e.com...


One of *my* biggest issues with conditional complication is that
compiling code conditionally often introduces undetected compilation


errors.

I'm not sure how a compilation error could be undetected, or do you mean a
programming error? Obviously, for performance and occupancy reasons, it's
very unusual for production code to include tracing so you do need some way
to build two versions (release & debug) from the same code.


This is a common problem with conditionally compiled code. Someone
updates an interface and breaks code that is not being compiled (because
of conditionally compiled elements) and someone else finds the problems
when they do compile those elements. One of the rules of good
programming is to find errors as soon as possible in the development cycle.

Code below is equivalent:
#if DO_STUFF

for ( .... lotsa code ... )
{
more code
}

#endif

.............. and ..........

if ( DO_STUFF )
for ( .... lotsa code ... )
{
more code
}
The code is essentially identical and if someone introduces an interface
issue in the "more code" section, it is found even if DO_STUFF is false
in the second version while not in the first.


Jul 22 '05 #12
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
Jarmo wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
Jarmo wrote:

"syncman" <hs***@hotmail.com> wrote in message
news:cc**************************@posting.googl e.com...
One of *my* biggest issues with conditional complication is that
compiling code conditionally often introduces undetected compilation


errors.

I'm not sure how a compilation error could be undetected, or do you mean a programming error? Obviously, for performance and occupancy reasons, it's very unusual for production code to include tracing so you do need some way to build two versions (release & debug) from the same code.


This is a common problem with conditionally compiled code. Someone
updates an interface and breaks code that is not being compiled (because
of conditionally compiled elements) and someone else finds the problems
when they do compile those elements. One of the rules of good
programming is to find errors as soon as possible in the development

cycle.

I think we're talking at cross-purposes. All I'm talking about here is
trace vs. non-trace, not about code that includes certain production
features depending upon how you compile it. There's no production code in
my conditional sections.
Jul 22 '05 #13
Jarmo wrote:
....

If the compiler completely optimizes out the TRACE code in the non-DEBUG
case, then that's fine. Otherwise the executable is larger than it has to
be, is slower to load, consumes more RAM, and conceivably suffers from at
least one unnecessary test for every single line of trace.


Consider it a bug if a compiler does not eliminate dead code.

Jul 22 '05 #14
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
Jarmo wrote:
...

If the compiler completely optimizes out the TRACE code in the non-DEBUG
case, then that's fine. Otherwise the executable is larger than it has to be, is slower to load, consumes more RAM, and conceivably suffers from at least one unnecessary test for every single line of trace.


Consider it a bug if a compiler does not eliminate dead code.


My regular (and reasonably up to date) win32 compiler produces executables
of identical size in both trace and non-trace mode with your method. With
my method they are different sizes (non-trace being smaller).

Also, and this is quite significant, the compiler generates numerous
"Condition is always true/false" warnings with your method (in both builds).

Now quite possibly I might find command line switches and/or pragmas for
this particular compiler that affect both of these (negative) outcomes but I
can pretty much guarantee that one cannot generally do so and hence any
attempt to write portable code for dozens of (old and new) compilers that
both compiles cleanly and is the optimal size probably cannot be done with
your method.
Jul 22 '05 #15
Jarmo wrote:
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:bu********@dispatch.concentric.net...
Jarmo wrote:
...
If the compiler completely optimizes out the TRACE code in the non-DEBUG
case, then that's fine. Otherwise the executable is larger than it has
to
be, is slower to load, consumes more RAM, and conceivably suffers from
at
least one unnecessary test for every single line of trace.
Consider it a bug if a compiler does not eliminate dead code.

My regular (and reasonably up to date) win32 compiler produces executables
of identical size in both trace and non-trace mode with your method. With
my method they are different sizes (non-trace being smaller).


I just tried VC++7.1 and gcc 3.3.1, both of them eliminated dead code
and the .o/.obj file contained none of the dead code.

Also, and this is quite significant, the compiler generates numerous
"Condition is always true/false" warnings with your method (in both builds).
Neither of the VC++7.1 or gcc 3.3.1 produced warnings.

Now quite possibly I might find command line switches and/or pragmas for
this particular compiler that affect both of these (negative) outcomes but I
can pretty much guarantee that one cannot generally do so and hence any
attempt to write portable code for dozens of (old and new) compilers that
both compiles cleanly and is the optimal size probably cannot be done with
your method.


Is the compiler broken ?

A size test with gcc gives:

DEBUG
- no-conditional code 3284 bytes (stripped)
- conditional code 3284 bytes (stripped)

NO DEBUG
- no-conditional code 2804 bytes (stripped)
- conditional code 2804 bytes (stripped) (has warnings)

i.e. identical results.

VC++7.1 gave identical sizes for all versions, however with disasssebly
listings it was obvious that the non conditional code example was
identical to the conditional code disassembly.

The code I used is below. Check it for yourself.
.............................................

#include <cstdio>
#include <cstdarg>

#if TEST1

#if defined(DEBUG)
#define TRACE(X) tracefunc X
#else
#define TRACE (void)

#endif

#else // TEST1

#if defined(DEBUG)
#define DOING_DEBUG 1
#else
#define DOING_DEBUG 0
#endif

#define TRACE(X) { if ( DOING_DEBUG ) { tracefunc X; } }

#endif // TEST1

#if defined(DEBUG)
namespace {

void tracefunc(char *format, ...)
{
va_list marker;
static FILE *fp = NULL;

if (!fp)
{
fp = fopen("tracef.trc", "w+t"); // open
}

if (fp)
{
va_start(marker, format);
vfprintf(fp, format, marker);
va_end(marker);
fputc('\n', fp);
fflush(fp);
}
}

};
#else
void tracefunc(char *format, ...);
#endif

int main(void)
{
int a = 1;
char *b = "BBBB";

TRACE(("a=%d, b=%s", a, b));
TRACE(("b=%s, a=%d", b, a));
}
Commands used :

setenv INL_CXXFLAGS "-DTEST1=1" ; rm deadcode2 ; m deadcode2 ; strip
deadcode2 ; ls -l deadcode2
setenv INL_CXXFLAGS "-DTEST1=1 -DDEBUG=1" ; rm deadcode2 ; m deadcode2 ;
strip deadcode2 ; ls -l deadcode2
setenv INL_CXXFLAGS "-DDEBUG=1" ; rm deadcode2 ; m deadcode2 ; strip
deadcode2 ; ls -l deadcode2
setenv INL_CXXFLAGS "" ; rm deadcode2 ; m deadcode2 ; strip deadcode2 ;
ls -l deadcode2
Jul 22 '05 #16
hs***@hotmail.com (syncman) wrote in message news:<cc**************************@posting.google. com>...
In C, I would always make a log() function instead of using printfs,
so that I could disable the messages or otherwise process them, all in
one place. This worked in 1 line, for constant strings, but not for
variable values, as in:
char s[99];
sprintf (s, "The value is %d \n", value);
log (s); // 3 lines!!

In C++, is it really as bad as it was? If I use streams:
ostringstream oss;
oss << "The value is " << value << endl;
log (oss.str());
No better!

I suspect the answer might be to use clog:
clog << "The value is " << value << endl;
But I don't see any place where I can later customize or disable.
(I read that clog is the same as cerr, but clog is buffered.)

So, how do people log?


Following is an exact cut and past of a response to a similar query not two
weeks ago. This sort of question about debugging macros etc, comes up
quite frequently yet I never tend to see anyone suggesting the following.
A better scheme is to harness the use of the C++ streams classes.

#ifdef DEBUG
#define tracer if (0) ; else cerr
#else
#define tracer if (1) ; else cerr
#endif

tracer << "something bad happened" << endl;

What is good about this is that you can format more than text strings, ie.,
anything which can be formatted into a stream. The code also looks more
natural as a result. And no the code will not be present when DEBUG isn't
defined as any sane compiler will realise the code in the else part can't
ever be called and leave it out.

For a look at a quite comprehensive debugging mechanism using these
concepts, look at the OSE library at "http://ose.sourceforge.net". There
is a chapter in the library manual on the program debugging support.
This might give you some ideas even if you want to stear clear of third
party libraries.
Jul 22 '05 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: William C. White | last post by:
Does anyone know of a way to use PHP /w Authorize.net AIM without using cURL? Our website is hosted on a shared drive and the webhost company doesn't installed additional software (such as cURL)...
2
by: Albert Ahtenberg | last post by:
Hello, I don't know if it is only me but I was sure that header("Location:url") redirects the browser instantly to URL, or at least stops the execution of the code. But appearantely it continues...
3
by: James | last post by:
Hi, I have a form with 2 fields. 'A' 'B' The user completes one of the fields and the form is submitted. On the results page I want to run a query, but this will change subject to which...
0
by: Ollivier Robert | last post by:
Hello, I'm trying to link PHP with Oracle 9.2.0/OCI8 with gcc 3.2.3 on a Solaris9 system. The link succeeds but everytime I try to run php, I get a SEGV from inside the libcnltsh.so library. ...
1
by: Richard Galli | last post by:
I want viewers to compare state laws on a single subject. Imagine a three-column table with a drop-down box on the top. A viewer selects a state from the list, and that state's text fills the...
4
by: Albert Ahtenberg | last post by:
Hello, I have two questions. 1. When the user presses the back button and returns to a form he filled the form is reseted. How do I leave there the values he inserted? 2. When the...
1
by: inderjit S Gabrie | last post by:
Hi all Here is the scenerio ...is it possibly to do this... i am getting valid course dates output on to a web which i have designed ....all is okay so far , look at the following web url ...
2
by: Jack | last post by:
Hi All, What is the PHP equivilent of Oracle bind variables in a SQL statement, e.g. select x from y where z=:parameter Which in asp/jsp would be followed by some statements to bind a value...
3
by: Sandwick | last post by:
I am trying to change the size of a drawing so they are all 3x3. the script below is what i was trying to use to cut it in half ... I get errors. I can display the normal picture but not the...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.