Pascal -> C

R

Ruud

Hallo allemaal,


In my Pascal program I gathered all messages in one function. All
messages have their own number. One of the advantages of this method
is that if someone wants to change a messages, he only has to look in
one place.

The function is declared as follow:
function zin(by : byte) : string;

A line calling the function can look like as simple as
this:
writeln(zin(12));

So far I have found a replacement for this function but I'm not
satisfied with it. I defined a 'char pst[255]' and the function 'void
zin(int by)' fills pst with the wanted message. But that means I now
need two lines instead of one:
zin(12);
printf("%s", pst);

Of course I tried to turn 'void zin(int by)' into a funtion that
returns a value so I could combine those two line to something like
'printf("%s", zin(12));' but I either got an compilation error or only
nonsense appeared on the screen.

In the meanwhile I found a solution in the form of
char *zin[20] = { "..", ""..." etc. }
printf("%s", zin[12]);

But that works fine for fixed messages but what about messages that
are generated by a function on the fly?

Any help is welcome!


--
___
/ __|__
/ / |_/ Groetjes, Ruud Baltissen
\ \__|_\
\___| http://Ruud.C64.org
 
N

Nick Keighley

In my Pascal program I gathered all messages in one function. All
messages have their own number. One of the advantages of this method
is that if someone wants to change a messages, he only has to look in
one place.

and if you want to know what a message is it's never in the
place where you look...

Very long macro names can help.

error (27);

and somewhere is
{27, "communications link is lost"}

hence a better macro might be
error (LINK_LOST);

I worked on a project where the error macros looked like this
error (SYSTEM_ERROR_COMMUNICATIONS_LINK_IS_LOST);

But this was internationalising (I18Ning) the actual output
strings.
The function is declared as follow:
function zin(by : byte) : string;

A line calling the function can look like as simple as
this:
writeln(zin(12));

So far I have found a replacement for this function but I'm not
satisfied with it. I defined a 'char pst[255]' and the function 'void
zin(int by)' fills pst with the wanted message. But that means I now
need two lines instead of one:
zin(12);
printf("%s", pst);

you could return static strings

const char* zin (int n)
{
switch (n)
{
case 1: return "link lost";
break;
case 2: return "O2 over pressure";
break;
default:
return "bad error code";
}
}

printf ("%s", zin(12));
Of course I tried to turn 'void zin(int by)' into a funtion that
returns a value so I could combine those two line to something like
'printf("%s", zin(12));' but I either got an compilation error or only
nonsense appeared on the screen.

show your code

In the meanwhile I found a solution in the form of
char *zin[20] = { "..", ""..." etc. }
printf("%s", zin[12]);

yep. Or

struct String_tab_entry
{
int n;
const char *str;
};

String_tab_entry string_tab [] =
{
{12, "tile lost"},
{99, "intruder"},
(101, "fire"},
};

Then search the array. The strings then don't have to be contiguous
or even ordered. (tho' ordered can make the search faster)
But that works fine for fixed messages but what about messages that
are generated by a function on the fly?

In that case you need a buffer of some sort. This is fairly
standard C problem. Solutions are

1. use a static buffer

const char* zin (int n, const char* arg)
{
static char buffer [256];

switch (n)
{
case 1:
sprintf (buffer, "link lost %s", arg);
return buffer;
}
}

Multiple calls may be a problem

printf ("%s %s", zin(12), zin(13));

2. pass a buffer

const char* zin (int n, char *buffer, const char* arg)
{ switch (n)
{
case 1:
sprintf (buffer, "link lost %s", arg);
return buffer;
}
}

3. malloc a buffer (but then someone has to clean up
afterwards).

4. Make zin() a lot cleverer (Untested code!)

#include <stdarg.h>

typedef void PrintFunc (const char*);

void zin (int n, PrintFunc *print, const char *format, ...)
{
va_list args;
va_start (args, format);
char buffer [256];
vsprintf (buffer, format, args);
print (buffer);
}

void print (const char *s)
{
printf ("%s", s);
}

zin (23, print, "link lost %d", link_id);


This is a bit untidy. But the point is you can pass arbitary
arguments to zin() using stdarg functionality. You can
also pass function arguments to do the actual i/o.

Without knowing more about your app I can't go any furthur.
Hope I've given you some ideas.
 
R

Richard Bos

Nick Keighley said:
and if you want to know what a message is it's never in the
place where you look...

Very long macro names can help.

error (27);

and somewhere is
{27, "communications link is lost"}

hence a better macro might be
error (LINK_LOST);

I worked on a project where the error macros looked like this
error (SYSTEM_ERROR_COMMUNICATIONS_LINK_IS_LOST);

Or in this case, even better, use an enum.

Richard
 
B

Ben Bacarisse

I was not going to post this but now the issue has come up twice it
seems worth it...

Nick Keighley said:
On 21 Oct, 09:38, Ruud <[email protected]> wrote:
But that works fine for fixed messages but what about messages that
are generated by a function on the fly?

In that case you need a buffer of some sort. This is fairly
standard C problem. Solutions are

1. use a static buffer

const char* zin (int n, const char* arg)
{
static char buffer [256];

switch (n)
{
case 1:
sprintf (buffer, "link lost %s", arg);
return buffer;
}
}

Multiple calls may be a problem

printf ("%s %s", zin(12), zin(13));

If you are stuck with this interface and need the above to work you
can, of course, allow a fixed number of "multiple" calls buy writing:

#define N_BUFFERS 3

const char* zin(int n, const char* arg)
{
static char buffers[N_BUFFERS][256];
static int nb = 0;
char *buffer = buffers[nb++];
nb %= N_BUFFERS;

/* code as before... */
}

but this has a relatively high "yuck" coefficient.
 
N

Nick Keighley

I was not going to post this but now the issue has come up twice it
seems worth it...







Nick Keighley said:
On 21 Oct, 09:38, Ruud <[email protected]> wrote:
In that case you need a buffer of some sort. This is fairly
standard C problem. Solutions are
   1. use a static buffer
   const char* zin (int n, const char* arg)
   {
       static char buffer [256];
       switch (n)
       {
           case 1:
                sprintf (buffer, "link lost %s", arg);
                return buffer;
       }
   }
   Multiple calls may be a problem
       printf ("%s %s", zin(12), zin(13));

If you are stuck with this interface and need the above to work you
can, of course, allow a fixed number of "multiple" calls buy writing:

    #define N_BUFFERS 3

    const char* zin(int n, const char* arg)
    {
        static char buffers[N_BUFFERS][256];
        static int nb = 0;
        char *buffer = buffers[nb++];
        nb %= N_BUFFERS;

        /* code as before... */
    }

but this has a relatively high "yuck" coefficient.

too true!

I tend to live with the static buffer. Live with
fact I *may* overflow it. And never have statements
with multiple uses of "zin()".
 
R

Ruud

Hallo allemaal,


@Richard:
you need to think about passing a buffer into the function.

That is one of the things I tried that did work. But passing a buffer
appeared a bit clumsy to me.
As I already mentioned, my original funtion 'zin' (FYI: Dutch for
'sentence') contains some concatinations with other variables which I
like to keep. So I think I have no choice then using this solution.


@Nick:
show your code

char pst[255];

main(int argc, char *argv[])
{
int by;

printf("\n\n\n");

for (by = 0; by < 2; by++)
printf("%s\n", szin(by));

return(0);
}


char szin(int w)
{
char *c;

switch(w)
{
case 0 : strcpy(pst, "Unknown/incorrect placed Directive");
break;
case 1 : strcpy(pst, "Line ended incorrectly");
break;
default : strcpy(pst, "?????????");
}

c = pst;
return(*c);
}


The above compiles fine but produces the nonsence. I'm quite sure it
has to do with 'c = pst' but what is wrong, I have no idea. 'pst' on
itself is a pointer (AFAIK). I can return '*c' but returning 'pst'
causes an error.
After writing the above I found a piece of code that explained some
things.

c = pst;

strcpy(pst, "abcdefgh");
c = pst;
printf("-1- %s\n", pst);
printf("-2- %c\n", *c);
printf("-3- %s\n", *c);
c = &pst[1];
printf("-4- %c\n", *c);
printf("-5- %s\n", *c);

return(*c);

Line -1- outputted 'abcdefgh', -2- 'a' and -4- 'b'. -3- and -5-
produce nonsence. Still the question: why can't I return 'pst'?


@Ben & Nick:

Thanks for the info but, being a beginner, these are things I don't
understand completely yet.


--
    ___
   / __|__
  / /  |_/     Groetjes, Ruud Baltissen
  \ \__|_\
   \___|      http://Ruud.C64.org
 
R

Richard Bos

Nick Keighley said:
why is an enum "better"?

It's cleaner, for starters. You have all your constants in one place
rather than a bunch of macros.

Richard
 
N

Nick Keighley

It's cleaner, for starters. You have all your constants in one place
rather than a bunch of macros.

I can put all the macros in one place.
Or I can have multiple "namespaces" with error
macros specific to different sub-systems
declared local to those systems. (I have seen
this done and spent a fair amount of time cursing
the lunatic who thought of it. grep is your fiend)

#define SYSTEM_ERROR_BASE 1000
#define SYSTEM_ERROR_GENERAL (SYSTEM_ERROR_BASE + 1)
#define SYSTEM_ERROR_WONT_START (SYSTEM_ERROR_BASE + 2)
#define SYSTEM_ERROR_HALT_BY_COMMAND (SYSTEM_ERROR_BASE + 3)
#define SYSTEM_ERROR_HALT_BY_TRAP (SYSTEM_ERROR_BASE + 4)


#define COMMS_ERROR_BASE (SYSTEM_ERROR_BASE + 10000)
#define COMMS_ERROR_LINK_LOST (COMMS_ERROR_BASE + 1)
#define COMMS_ERROR_BER_HIGH (COMMS_ERROR_BASE + 2)
#define COMMS_ERROR_FRAMING (COMMS_ERROR_BASE + 3)
#define COMMS_ERROR_UNKOWN_ADDRESS (COMMS_ERROR_BASE + 4)
 
I

Ian Collins

Nick said:
I can put all the macros in one place.
Or I can have multiple "namespaces" with error
macros specific to different sub-systems
declared local to those systems. (I have seen
this done and spent a fair amount of time cursing
the lunatic who thought of it. grep is your fiend)

#define SYSTEM_ERROR_BASE 1000
#define SYSTEM_ERROR_GENERAL (SYSTEM_ERROR_BASE + 1)
#define SYSTEM_ERROR_WONT_START (SYSTEM_ERROR_BASE + 2)
#define SYSTEM_ERROR_HALT_BY_COMMAND (SYSTEM_ERROR_BASE + 3)
#define SYSTEM_ERROR_HALT_BY_TRAP (SYSTEM_ERROR_BASE + 4)
So that's cleaner and less error prone than

enum SystemError
{
SYSTEM_ERROR_BASE = 1000,
SYSTEM_ERROR_GENERAL,
SYSTEM_ERROR_WONT_START,
SYSTEM_ERROR_HALT_BY_COMMAND,
SYSTEM_ERROR_HALT_BY_TRAP
};

?
 
R

Ruud

Hallo Richard & Spiro,

char *szin(int w)

Spiro just emailed me the same in a PM. And this works!
Thank you both !!!

Having a good look at it it is all logical. 'printf' expects an
pointer and '*szin' returns one, something 'szin' didnit.


--
___
/ __|__
/ / |_/ Groetjes, Ruud
\ \__|_\
\___| URL: Ruud.C64.org
 
N

Nick Keighley

So that's cleaner and less error prone than

enum SystemError
{
  SYSTEM_ERROR_BASE = 1000,
  SYSTEM_ERROR_GENERAL,
  SYSTEM_ERROR_WONT_START,
  SYSTEM_ERROR_HALT_BY_COMMAND,
  SYSTEM_ERROR_HALT_BY_TRAP

};

?

ah, I should ahve stressed the second lot (the comms ones)
were in a different file (actaully different package)
from the general ones. Yes it has its downside but
on a large project there might be reasons for different
sub-systems to have semi-independent error list.

I reality some of this was code generated by a CASE tool

"cleaness" of code is another on of those opinion
thingies
 
M

Michael

Ruud said:
Hallo allemaal,


In my Pascal program I gathered all messages in one function. All
messages have their own number. One of the advantages of this method
is that if someone wants to change a messages, he only has to look in
one place.

The function is declared as follow:
function zin(by : byte) : string;

A line calling the function can look like as simple as
this:
writeln(zin(12));

So far I have found a replacement for this function but I'm not
satisfied with it. I defined a 'char pst[255]' and the function 'void
zin(int by)' fills pst with the wanted message. But that means I now
need two lines instead of one:
zin(12);
printf("%s", pst);

Of course I tried to turn 'void zin(int by)' into a funtion that
returns a value so I could combine those two line to something like
'printf("%s", zin(12));' but I either got an compilation error or only
nonsense appeared on the screen.

In the meanwhile I found a solution in the form of
char *zin[20] = { "..", ""..." etc. }
printf("%s", zin[12]);

But that works fine for fixed messages but what about messages that
are generated by a function on the fly?

Any help is welcome!


--
___
/ __|__
/ / |_/ Groetjes, Ruud Baltissen
\ \__|_\
\___| http://Ruud.C64.org
pascal:
function zin(by : byte) : string;

c++:
string zin(unsigned char by);


pascal
writeln(zin(12));

c++:

cout<<zin(12);


No pure C solution is available because pure C has no string type.
 
F

Flash Gordon

Nick Keighley wrote, On 22/10/08 11:54:
ah, I should ahve stressed the second lot (the comms ones)
were in a different file (actaully different package)
from the general ones.

That does not make the enum approach any harder...
enum CommsErrors {
COMMS_ERROR_BASE = SYSTEM_ERROR_BASE + 10000,
...
Yes it has its downside but
on a large project there might be reasons for different
sub-systems to have semi-independent error list.

For this type of thing as long as they are integers within the range
supported for enum on the implementation I find it incredibly hard to
see a situation where you could use the #define approach and not the
enum approach.
I reality some of this was code generated by a CASE tool

Well, with auto-generated code you often don't care about looks :)
"cleaness" of code is another on of those opinion
thingies

Indeed. I prefer the enum approach myself though.
 
I

Ian Collins

Flash said:
Nick Keighley wrote, On 22/10/08 11:54:


Indeed. I prefer the enum approach myself though.

And don't forget if you use enums, you can compile your code with a C++
compiler to make sure you only use valid values :)
 
R

Ruud

Hallo Michael,
pascal:
function zin(by : byte) : string;

c++:
string zin(unsigned char by);

pascal
writeln(zin(12));

c++:

cout<<zin(12);

No pure C solution is available because pure C has no string type.

Very interesting indeed, thank you!

--
___
/ __|__
/ / |_/ Groetjes, Ruud
\ \__|_\
\___| URL: Ruud.C64.org
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top