I am trying to compile the following code in Cygwin 64 bit terminal using gcc, but it seems to be unable to find conio.h or dos.h
#include <stdlib.h>
#include <dos.h>
#define MEM 0X12
main()
{
struct WORDREGS
{
unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
unsigned int si;
unsigned int di;
unsigned int flags;
};
struct BYTEREGS
{
unsigned char al,ah;
unsigned char bl,bh;
unsigned char cl,ch;
unsigned char dl,dh;
};
union REGS
{
struct WORDREGS x;
struct BYTEREGS h;
};
union REGS regs;
unsigned int size;
int86(MEM, ®s, ®s);
size = regs.x.ax;
printf("Memory size is %d Kbytes", size);
}
The compiler says it is unable to locate dos.h or conio.h, showing a fatal error notice. I want to know what the reason for this is and how it can be dealt with.
Cygwin is a Linux-Environment for Windows (see https://cygwin.com ). This is probably the main reason because there very well exists a header file called 'dos.h'.
Concerning the compilation problem a solution is explained in the mail archive of the cygwin mailing list ( https://www.cygwin.com/ml/cygwin/2007-04/msg00180.html ).
It seems that dos.h and conio.h (header-files) are part of the mingw-runtime-WHATEVER.VERSION package, which you can download from cygwin.com (better install it with the cygwin install and update program setup-x86.exe or setup-x86_64.exe).
The link in that mail mentioned above is broken, but you can find the package by yourself, when choosing 'Search Packages' on the left side bar of the cygwin.com homepage. Then you can put 'dos.h' or 'conio.h' into the input field and after hitting 'Go' you get listed all packages, which contain these header files. According to the answer in that mail above, you only need the
mingw-runtime-WHATEVER.VERSION package, which you have to download and install.
After installing that package you very probably need to instruct your gcc-compiler with the
option '-I' (upper-case letter 'i'!) and the path (within quotation marks!) to the dos.h file, for instance:
gcc program.c -I'C:\cygwin\usr\i686-pc-mingw32\sys-root\mingw\include'
Attention: Probably the path on your system is different, particularly when you are working with 64-bit-cygwin!
Instead of using the '-I' option, you can define an environment variable with following command in the terminal:
export C_INCLUDE_PATH='C:\cygwin\usr\i686-pc-mingw32\sys-root\mingw\include'
At least the errors with the not found header-files are then eliminated, but there are probably still other errors (for instance: undefined reference to 'int86'?).
Because they are MS-DOS headers and are not available in cygwin. Also, the correct signature of main() is int main().
Related
I'm writing a file parser in C using gcc on Windows using MSYS2.
Using pacman I've downloaded the required libraries for using libbzip2.
For some reason, I can include the bzlib.h file and use the structures it contains, but not its functions.
Here's my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <bzlib.h>
void init_decompress_stream(bz_stream *stream, char *next_in, unsigned int avail_in, char *next_out, unsigned int avail_out);
int main(){
// Open FILE
FILE *ptr;
ptr = fopen("example.bin", "rb");
// Read Metadata
int metadata[10];
fread(metadata, sizeof(int), 10, ptr);
// Init stream
bz_stream *stream;
unsigned int avail_in = metadata[0] * sizeof(char);
unsigned int avail_out = metadata[1] * sizeof(int);
char *compressed_data = malloc(avail_in);
char *data = malloc(avail_out);
// Read data
fread(compressed_data, 1, avail_in, ptr);
init_decompress_stream(stream, compressed_data, avail_in, data, avail_out);
// Decompress data -- COMPILES FINE UNTIL HERE --
int bz_result = BZ2_bzDecompressInit(stream, 0, 0);
}
void init_decompress_stream(bz_stream *stream, char *next_in, unsigned int avail_in, char *next_out, unsigned int avail_out){
stream->next_in = next_in;
stream->avail_in = avail_in;
stream->next_out = next_out;
stream->avail_out = avail_out;
}
This all compiles fine until the last line of main: int bz_result = BZ2_bzDecompressInit(stream, 0, 0);
when I compile using at which point I get the error:
C:/msys64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\{User Name}\AppData\Local\Temp\cct30tb5.o:test.c(.text+0xc4): undefined reference to 'BZ2_bzDecompressInit'
collect2.exe: error: ld returned 1 exit status
While troubleshooting I've used three different compile commands:
gcc test.c This compiles #include <bzlib.h> and bz_stream *stream; just fine until the last line.
gcc test.c -L/usr/lib/libbz2.a this performs same as above.
gcc test.c -libbz2 this one cannot find -libbz2
I'm totally perplexed as to what I'm doing wrong.
In gcc, -L add a directory to the library search path, and -l specifies a library to load (using the search path to find it).
Hence you probably need something like:
gcc test.c -L /usr/lib -l bz2
I'd be surprised if /usr/lib wasn't already on the library path but you may want to specify it just in case. And the toolchain is smart enough to prefix your library names with lib and suffix them with extensions as needed.
You should be aware that gcc test.c -libbz2 is probably equivalent to gcc test.c -l ibbz2 which is going to be looking for ibbz2, not what you wanted.
I am doing some protocol stack programming with golang. I put codec thing in C. And build C with a simple CMake configuration as below:
cmake_minimum_required (VERSION 2.8)
project (Demo1)
aux_source_directory(. DIR_SRCS)
add_library(codecLib SHARED ${DIR_SRCS})
and Link the shared library with this kind code
//#cgo CFLAGS:-I./codec/
//#cgo LDFLAGS: ./codec/build -lcodecLib
//#include <protocol.h>
import "C"
import "fmt"
at last, I met following error while building it with command
"CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build",
In file included from /usr/include/stdlib.h:42:0,
from _cgo_export.c:2:
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:79:15: error: duplicate member ‘__w_retcode’
unsigned int __w_retcode:8;
^
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:80:15: error: duplicate member ‘__w_coredump’
unsigned int __w_coredump:1;
^
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:81:15: error: duplicate member ‘__w_termsig’
unsigned int __w_termsig:7;
^
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:93:15: error: duplicate member ‘__w_stopsig’
unsigned int __w_stopsig:8; /* Stopping signal. */
^
/usr/include/x86_64-linux-gnu/bits/waitstatus.h:94:15: error: duplicate member ‘__w_stopval’
unsigned int __w_stopval:8; /* W_STOPPED if stopped. */
I didn't find the solution yet. I appreciate for the solution.
The problem you're having is probably due to GOLang not parsing the pre-processor commands in the GNU C Library properly (or at all). It could also be due to an issue with your importing endian.h, or requiring some other C/GO/CGO import or define.
Here's an excerpt from waitstatus.h (or see the full file on GitHub):
# if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int __w_termsig:7;
unsigned int __w_coredump:1;
unsigned int __w_retcode:8;
unsigned int:16;
# endif /* Little endian. */
# if __BYTE_ORDER == __BIG_ENDIAN
unsigned int:16;
unsigned int __w_retcode:8;
unsigned int __w_coredump:1;
unsigned int __w_termsig:7;
# endif /* Big endian. */
You'll notice that the same variables are announced twice - one for each Endian. GOLang is erroring because of this. You could resolve this by manually editing the file if you know which endian you're compiling for.
I'm trying to get some old legacy code working on new 64-bit systems, and I'm currently stuck. Below is a small C file I'm using to test functionality that exists in the actual program that is currently breaking.
#define _POSIX_SOURCE
#include <dirent.h>
#include <sys/types.h>
#undef _POSIX_SOURCE
#include <stdio.h>
main(){
DIR *dirp;
struct dirent *dp;
char *const_dir;
const_dir = "/any/path/goes/here";
if(!(dirp = opendir(const_dir)))
perror("opendir() error");
else{
puts("contents of path:");
while(dp = readdir(dirp))
printf(" %s\n", dp->d_name);
closedir(dirp);
}
}
The Problem:
The OS is Red Hat 7.0 Maipo x86_64.
The legacy code is 32-bit, and must be kept that way.
I've gotten the compile for the program working fine using the -m32 flag with g++. The problem that arises is during runtime, readdir() gets a 64-bit inode and then throws an EOVERFLOW errno and of course nothing gets printed out.
I've tried using readdir64() in place of readdir() to some success. I no longer get the errno EOVERFLOW, and the lines come out on the terminal, but the files themselves don't get printed. I'm assuming this is due to the buffer not being what dirent expects.
I've attempted to use dirent64 to try to alleviate this problem but whenever I attempt this I get:
test.c:19:22 error: dereferencing pointer to incomplete type
printf(" %s\n", dp->d_name);
I'm wondering if there's a way to manually shift the dp->d_name buffer for dirent to be used with readdir(). I've noticed in Gdb that using readdir() and dirent results in dp->d_name having directories listed at dp->d_name[1], whereas readdir64() and dirent gives the first directory at dp->d_name[8].
That or somehow get dirent64 to work, or maybe I'm just on the wrong path completely.
Lastly, it's worth noting that the program functions perfectly without the -m32 flag included, so I'm assuming it has to be a 32/64 compatibility error somewhere. Any help is appreciated.
Thanks to #Martin in the comments above I was led to try defining the dirent64 struct in my code. This works. There's probably a #define that can be used to circumvent pasting libc .h code into my own code, but this works for now.
The code I needed was found in <bits/dirent.h>
I guess I should also note that this makes it work using both readdir64() and dirent64
In order to get a 64-bit ino_t with GCC and Glibc, you need to define the features _XOPEN_SOURCE and _FILE_OFFSET_BITS=64.
$ echo '#include <dirent.h>' | gcc -m32 -E -D_XOPEN_SOURCE -D_FILE_OFFSET_BITS=64 - | grep ino
__extension__ typedef unsigned long int __ino_t;
__extension__ typedef __u_quad_t __ino64_t;
typedef __ino64_t ino_t;
__ino64_t d_ino;
I say this from documentation reading and checking the preprocessor, not from deep experience or testing with a filesystem with inode numbers above 2^32, so I don't guarantee that you won't run into other problems down the line.
I had a problem with a part of my code, which after some iterations seemed to read NaN as value of a double of a struct. I think I found the error, but am still wondering why gcc (version 3.2.3 on a embedded Linux with busybox) did not warn me. Here are the important parts of the code:
A c file and its header for functions to acquire data over USB:
// usb_control.h
typedef struct{
double mean;
short *values;
} DATA_POINTS;
typedef struct{
int size;
DATA_POINTS *channel1;
//....7 more channels
} DATA_STRUCT;
DATA_STRUCT *create_data_struct(int N); // N values per channel
int free_data_struct(DATA_STRUCT *data);
int aqcu_data(DATA_STRUCT *data, int N);
A c and header file with helper function (math, bitshift,etc...):
// helper.h
int mean(DATA_STRUCT *data);
// helper.c (this is where the error is obviously)
double mean(DATA_STRUCT *data)
{
// sum in for loop
data->channel1->mean = sum/data->N;
// ...7 more channels
// a printf here displayed the mean values corretly
}
The main file
// main.c
#include "helper.h"
#include "usb_control.h"
// Allocate space for data struct
DATA_STRUCT *data = create_data_struct(N);
// get data for different delays
for (delay = 0; delay < 500; delay += pw){
acqu_data(data, N);
mean(data);
printf("%.2f",data->channel1->mean); // done for all 8 channels
// printf of the mean values first is correct. Than after 5 iterations
// it is always NaN for channel1. The other channels are displayed correctly;
}
There were no segfaults nor any other missbehavior, just the NaN for channel1 in the main file.
After finding the error, which was not easy, it was of course east to fix. The return type of mean(){} was wrong in the definition. Instead of double mean() it has to be int mean() as the prototype defines. When all the functions are put into one file, gcc warns me that there is a redefinition of the function mean(). But as I compile each c file seperately and link them afterwards gcc seems to miss that.
So my questions would be. Why didn't I get any warnings, even non with gcc -Wall? Or is there still another error hidden which is just not causing problems now?
Regards,
christian
When each .c file is compiled separately, the only information the compiler knows is the function prototype you have given.
Because every file is compiled separately, there is no way the compiler process of main.c knows the definition of mean in helper.c is wrong.
After the .c file is compiled, the signature will be stripped, so the linker cannot know the mean is wrong either.
A simple fix is always include the interface .h file in the implementation .c file
// in helper.c:
#include "helper.h"
double mean(DATA_STRUCT *data);
Then the compiler process of helper.c will notice that inconsistent type and warn you.
A mean usually is a real value so double is ok. Here you define mean as returning double, but the prototype says int mean(...).
The only way gcc can be aware of the fact that there's a redefinition, is if the redefinition occurs for real... When you compile files separately likely the mean prototype is missing... it is not shown in your code fragment at least: you should include helper.h also into helper.c. Doing so, gcc -c helper.c must give you a warning. I have gcc 4.3.2, but I am almost sure it must be so also for the version you have. In the main, you just use mean, so here the gcc trusts what is said in helper.h. When you link, there is no more information about the size of arguments and returning value, and bad things happen (like reading an int as a double).
Another detail: you say you get NaN for an int of the struct... well, in the struct there's a double, and int can't be NaN!
The compiler doesn't know where stat.h is?
Error:
c:\Projects\ADC_HCI\mongoose.c(745) : error C2079: 'st' uses undefined struct '_stat64'
#include <sys/types.h>
#include <sys/stat.h>
static int
mg_stat(const char *path, struct mgstat *stp)
{
struct _stat64 st; //<-- ERROR
int ok;
wchar_t wbuf[FILENAME_MAX];
to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
if (_wstat64(wbuf, &st) == 0) {
ok = 0;
stp->size = st.st_size;
stp->mtime = st.st_mtime;
stp->is_directory = S_ISDIR(st.st_mode);
} else {
ok = -1;
}
return (ok);
}
...downloaded the files straight from the source.
See MSDN: _wstat64 takes a parameter of struct __stat64 (with two underscores). Redeclare your variable st to be of type struct __stat64.
Note that neither _stat64 nor __stat64 is 'standard' in the sense of documented by any standard, such as POSIX. You would normally use struct stat; if you are worried about whether that will work with big files (over 2 GiB), then check what compilation options are required on your platform to obtain 'large file support'. For 64-bit machines and 64-bit compilations (not necessarily Windows 64), you usually don't need to worry. You can often obtain large file support using:
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
These are at least semi-standardized. Systems such as autoconf detect these things automatically (if you ask them to do so).
Change the _stat64 to stat64. At least in my Linux machines that's the name of the structure. I don't know if it is different in Windows.
I suggest you to sync to SVN trunk.
If you don't have SVN client, simply download two files:
http://mongoose.googlecode.com/svn/trunk/mongoose.h (and .c file too)
The reason is that recently the code was refactored, and CRT _stat function was substituted
with WinAPI one, GetFileAttributesExW().