Solved

Far pointers and DJGPP

Posted on 2004-09-09
23
353 Views
Last Modified: 2008-02-01
Hello everyone,

I have this simple and little code that should print out like Unix banner command...

#include <stdlib.h>
#include <conio.h>

int writechar(char ch, int i);

writechar ( ch, i )
{
      char ch;
      int i;

      int l, row = 1, col;
      char far *ch1;
      unsigned char mask;
      col = i * 8 + 1;

      /* find bit settings of scan line in the charcter */
      for ( l = 0 ; l <= 7 ; l++ )
      {
            /* collect the address of bitmap of the character */       
            ch1 = (char far *)0xFFA6000EL + (ch * 8) + l;
            mask = 128;

            while ( mask )             
            {
                  /* if the bit is ON */
                  if ( ( *ch1 ) & mask )
                  {
                        gotoxy ( col, row );
                        printf ( "%c", '#' );
                  }  
                  col++;
                  mask = mask >> 1;
            }
            col = i * 8 + 1;
            row++;
      }
}

int main ( int argc, char *argv[] )
{
      int i = 0;

      clrscr();

      /* output maximum of 10 characters */

      for ( i = 0 ; i < 10 ; i++ )
      {
            /* if end of string is reached */
            if ( argv[1][i] == '\0' ) break;
            writechar ( argv[1][i], i );                         
      }
}

I'm trying to compile it with DJGPP but I always get this error:

C:\TEST_C~1\src\banner>gcc banner.cpp -o banner.o
banner.cpp:6: error: expected constructor, destructor, or type conversion before
 '(' token
banner.cpp:6: error: expected `,' or `;' before '(' token

I thought it's cause far pointers aren't accepted by DJGPP... in this case what I can use instead of far pointers?

Thanks to everyone...
Ciao, Luigi
0
Comment
Question by:npuleio
  • 13
  • 9
23 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 12014045
int writechar(char ch, int i)
{
     char ch;
     int i;

...
0
 

Author Comment

by:npuleio
ID: 12014352
Ah that's it... but I figured anyway as I was fearing of..a problem with far pointers and DJGPP... in fact I get those errors around char far *:

C:\TEST_C~1\src\banner>gcc banner.cpp -o banner.o
banner.cpp: In function `int writechar(char, int)':
banner.cpp:12: error: expected primary-expression before "char"
banner.cpp:12: error: expected `;' before "char"
banner.cpp:20: error: `ch1' undeclared (first use this function)
banner.cpp:20: error: (Each undeclared identifier is reported only once for each
 function it appears in.)
banner.cpp:20: error: expected primary-expression before "char"
banner.cpp:20: error: expected `)' before "char"
banner.cpp:29: error: `printf' undeclared (first use this function)

is there a DJGPP option or an alternative idea instead of using char far *?

Thanks
Ciao, Luigi
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014452
Try:

#define far

Since you are using 32-bit pointers, there is no need for the far keyword.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014468
I'd be surprised if the following was portable from 16-bit to 32-bit though:

ch1 = (char far *)0xFFA6000EL + (ch * 8) + l;

If your code has been taken from a 16-bit project, you might be better off going to the Borland Museum to get a 16-bit compiler.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014479
Also...

> writechar ( ch, i )

...looks like K&R style C, assuming that ch and i are ints. You'll need to compile this as C rather than C++.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014485
Actually, for K&R style C parameters you need...

--------8<--------
writechar ( ch, i )
char ch;
{
/*     char ch;
     int i;*/
--------8<--------
0
 

Author Comment

by:npuleio
ID: 12014515
Mmmmm did that and compiled it but trying to execute it I get this:

Exiting due to signal SIGSEGV
General Protection Fault at eip=0000162c
eax=ffa6038e ebx=00000167 ecx=00000000 edx=006e0b7c esi=00000054 edi=00011f84
ebp=006dffa8 esp=006dff90 program=C:\TEST_C~1\SRC\BANNER\BANNER.EXE
cs: sel=01a7  base=01670000  limit=006effff
ds: sel=01af  base=01670000  limit=006effff
es: sel=01af  base=01670000  limit=006effff
fs: sel=017f  base=00007350  limit=0000ffff
gs: sel=01bf  base=00000000  limit=0010ffff
ss: sel=01af  base=01670000  limit=006effff
App stack: [006e0000..00660000]  Exceptn stack: [00011ee4..0000ffa4]

Call frame traceback EIPs:
  0x0000162c
  0x000016e7
  0x00002ea8

I guess since it compiled ok with: gcc banner.c -o banner.exe without errors.... what could be? Forgot maybe some compiler option to add in the gcc command line?

Thanks
ciao, Luigi
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014517
To get it to compile you need:

--------8<--------
#include <stdlib.h>
#include <conio.h>

#define far

/*int*/ writechar(char ch, int i);

writechar ( ch, i )
char ch;
{
/*     char ch;
     int i;*/

     int l, row = 1, col;
     char far *ch1;
     unsigned char mask;
     col = i * 8 + 1;

     /* find bit settings of scan line in the charcter */
     for ( l = 0 ; l <= 7 ; l++ )
     {
          /* collect the address of bitmap of the character */
          ch1 = (char far *)0xFFA6000EL + (ch * 8) + l;
          mask = 128;

          while ( mask )
          {
               /* if the bit is ON */
               if ( ( *ch1 ) & mask )
               {
                    gotoxy ( col, row );
                    printf ( "%c", '#' );
               }
               col++;
               mask = mask >> 1;
          }
          col = i * 8 + 1;
          row++;
     }
}

int main ( int argc, char *argv[] )
{
     int i = 0;

     clrscr();

     /* output maximum of 10 characters */

     for ( i = 0 ; i < 10 ; i++ )
     {
          /* if end of string is reached */
          if ( argv[1][i] == '\0' ) break;
          writechar ( argv[1][i], i );
     }
}
--------8<--------

You'll need to link the library with gotoxy and clrscr. You may find that these aren't available in DJGPP and you need to write your own version. Like I said, I'm very dubious about the:

> ch1 = (char far *)0xFFA6000EL + (ch * 8) + l;

It is unlikely to be something that works in protected mode. It looks like something that reads data from BIOS in real mode DOS.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014536
If you do get a 16-bit compiler from the Borland museum (the Borland DOS copilers do have gotoxy and clrscr), you can compile the code above using a large or compact memory model (or simply comment out the #define far). Remember to call the file banner.c to get it to compile as C rather than C++, because the K&R style function doesn't work for C++.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014548
> General Protection Fault

That's to be expected because you are attempting to access BIOS memory. The program was designed for real mode DOS.
0
 

Author Comment

by:npuleio
ID: 12014668
OK, getting Turbo C 2.01 and removing the #define far it compiles OK and executing I get what I want on screen but if I do something like this:

banner "Eng. Michael Moore" > c:\screen.txt

I get like a line of # and not what I see on da screen...why? shouldn't just print on a file what it prints on a screen?

Thanks
ciao, Luigi
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 17

Expert Comment

by:rstaveley
ID: 12014719
>                     printf ( "%c", '#' );

It prints '#'.

What do expect this to do?
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12014732
The banner looks OK, if you don't redirect to a file.

e.g.

 banner "Hello"

gotoxy positions the screen scursor, but doesn't have any effect on stdout.
0
 

Author Comment

by:npuleio
ID: 12014765
Uhm guess I have to use something else if I want to start to write just next the command executing without clearing the screen right? like I should get the current line position and adding + 1... but how to get the current line position in C?...

Thanks!
Ciao, Luigi
0
 
LVL 17

Accepted Solution

by:
rstaveley earned 125 total points
ID: 12015135
#include <stdlib.h>
#include <conio.h>

/*#define far*/
static int initial_row;

/*int*/ writechar(char ch, int i);

writechar ( ch, i )
char ch;
{
/*     char ch;
     int i;*/

     int l, row = initial_row+1, col;
     char far *ch1;
     unsigned char mask;
     col = i * 8 + 1;

     /* find bit settings of scan line in the charcter */
     for ( l = 0 ; l <= 7 ; l++ )
     {
          /* collect the address of bitmap of the character */
          ch1 = (char far *)0xFFA6000EL + (ch * 8) + l;
          mask = 128;

          while ( mask )
          {
               /* if the bit is ON */
               if ( ( *ch1 ) & mask )
               {
                    gotoxy ( col, row );
                    printf ( "%c", '#' );
               }
               col++;
               mask = mask >> 1;
          }
          col = i * 8 + 1;
          row++;
     }
}

int main ( int argc, char *argv[] )
{
     int i = 0;

     /*clrscr();*/
     initial_row = wherey();
     while (initial_row+9 > 24) {
             printf("\n");
             initial_row--;
     }


     /* output maximum of 10 characters */

     for ( i = 0 ; i < 10 ; i++ )
     {
          /* if end of string is reached */
          if ( argv[1][i] == '\0' ) break;
          writechar ( argv[1][i], i );
     }

     gotoxy(0,initial_row+9);
}
0
 

Author Comment

by:npuleio
ID: 12015286
Thanks rstaveley, that works fine on da screen...
just only a little detail, if I want to print on da file what I print out on da screen like a successive operation after printing out:

banner "HELLO" > c:\text.txt

shall I maybe have to re-consider the printf thing using something else?

Thanks!
Ciao, Luigi
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12015379
You could use a 2D array of characters, which you initialise with spaces.

i.e.

    char line[8][80+1];
    memset(&line,' ',81*8);
    for (i = 0;i < 8;i++)
        line[i][80] = '\0';

Instead of gotoxy(20,3) followed by printf("#");, take a char pointer to &line[3][20] and poke '#' into the location.

Finally,

    for (i = 0;i < 8;i++)
        fprintf(yourfile,"%s\n",line[i]);

Get the idea?
0
 

Author Comment

by:npuleio
ID: 12015902
That would mean instead to have:

gotoxy(20,3);
printf("%c", '*');

I'll have:

line[3][20]='*';

because it is a wide matrix of 640 blocks if I remember good. Am I right?

Ciao, Luigi
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12016432
> line[3][20]='*';

Yes, that's fine too
0
 

Author Comment

by:npuleio
ID: 12017163
Thanks....I'll have just to fix some little stuffs around that line[..][..] but looks like I'm close to the final result...

Ciao, Luigi
0
 

Author Comment

by:npuleio
ID: 12024292
Hiya again rstaveley,

maybe you could help me a bit..I've modified temporarily the code to write in an array as you suggested me which's a good idea to write in a file...since sometimes looks fine, other times it shows strange... maybe shall I have missed something in the code?

 #include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>

static int initial_row;
char line[8][80+1];
int colonne = 0;

writechar(char ch, int i);

writechar ( ch, i )
char ch;
{
     int l, row = initial_row+1, col;
     char far *ch1;
     unsigned char mask;
     int linee;
     col = i * 8 + 1;

     if ( colonne == 10 ) linee = 7;
     else linee = 8;
     /* find bit settings of scan line in the charcter */
     for ( l = 0 ; l <= linee ; l++ )
     {
          /* collect the address of bitmap of the character */
          ch1 = (char far *)0xFFA6000EL + (ch * 8) + l;
          mask = 128;

          while ( mask )
          {
               /* if the bit is ON */
               if ( ( *ch1 ) & mask )
             {
              if ( colonne == 10 ) {
                gotoxy ( col, row );
                printf( "%c", '*' );
              }
              else
              {
                line[row][col] = '*';
              }
               }
               col++;
               mask = mask >> 1;
          }
        col = i * 8 + 1;
          row++;
     }
}

int main ( int argc, char *argv[] )
{
     int i = 0;
     int counter;
     char myString[]="";
     int lunghezza=0;

     if ( argv[1][0] == 'S' ) colonne = 10;
     if ( argv[1][0] == 'F' ) {
       colonne = 99;
       memset(&line, ' ', 81*8);
       for ( i = 0; i <= 8; i++ )
       line[i][80] = '\0';
     }

     if ( colonne == 10 ) {
       initial_row = wherey();
       while (initial_row+9 > 24) {
            printf("\n");
            initial_row--;
       }
     }
     else initial_row = 0;

     counter = argc;
     if ( colonne == 10 ) {
       lunghezza = 9;
     }
     else
     {
       lunghezza = strlen(argv[2]);
     }

     /* output maximum of 10 characters */
     for ( i = 0 ; i <= lunghezza ; i++ )
     {
          /* if end of string is reached */
        if ( argv[2] == '\0' ) break;
        writechar ( argv[2][i], i );
     }

     if (colonne == 10) {
       gotoxy(0,initial_row+10);
       printf("\n\n\n");
     }
     else {
       for ( i = 0; i <= 8; i++ )
       printf("%s", line[i]);
     }

}

Thanks!
Ciao, Luigi
0
 

Author Comment

by:npuleio
ID: 12025060
I guess I've figured out... just only a little question... when I have to use fopen, how I can allow long paths like C:\MYDOCUMENTSPATH\TEST.TXT?

Thanks
Ciao, Luigi
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12025164
With a 16-bit compiler you need to use 8.3 filenames i.e. most probably c:\mydocu~1\test.txt for c:\My documents\test.txt.

You can see the 8.3 filenames if you use the /x switch when you do a DOS directory listing.

i.e. Start | Run | cmd | dir /x c:\my*

The rule of thumb is to remove spaces and then take the first 6 characters of the filename followed by ~1 (for the first match).
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now