I am working on making a boolean expression evaluator in lex and c, however I am having problem finding the error in my code.
When I run the code the parser.c file throws the error("expected end-of-file"). This means that the program is not reading the end of file character, and I cannot find where this is going wrong.
I have attached the problematic code below. If, to solve this issue you need to see some more of the code please let me know, and I will be happy to post them also. I have been stuck on this problem for several weeks not, any help would be greatly appreciated.
Lexer.h
#ifndef ____lexer__
#define ____lexer__
#include <stdio.h>
#define AND 258
#define OR 259
#define NOT 260
#define TRUE 261
#define FALSE 262
#define DONE 300
#define NONE (-1)
int lexan();
extern int value;
extern int lineNo;
extern char lexbuf[];
extern FILE *fileSource;
#endif /* defined(____lexer__) */
lexer.lex
%{
#include <ctype.h>
#include <unistd.h>
#include "lexer.h"
#include "error.h"
int value;
int lineNo;
%}
%option noyywrap
%%
['''\t']* {}
['\n']* { lineNo++; }
<<EOF>> {
return DONE;
}
"True" {return (TRUE);}
"False" {return (FALSE);}
"or" {return (OR);}
"and" {return (AND);}
"not" {return (NOT);}
.|\n {
value = NONE;
int temp = (int)(yytext[0]);
return (temp);
}
%%
int lexan()
{
yyin = fileSource;
int result = yylex();
return result;
}
parser.c
#include <stdlib.h>
#include "parser.h"
#include "lexer.h"
#include "error.h"
#include "interpreter.h"
static int lookahead;
static void stmts();
static void stmt();
static void assign();
static void expr();
static void match();
void parse()
{
lookahead = lexan();
stmts();
lookahead = lexan();
if(lookahead != DONE)
error("expected end-of-file");
}
static void stmts()
{
while (lookahead != DONE)
{
if(lookahead == AND || lookahead == OR || lookahead == NOT || lookahead == TRUE || lookahead == FALSE)
{
stmt();
}
else
break;
}
}
static void stmt()
{
switch (lookahead)
{
case AND:
emit(AND);
match(AND);
break;
case OR:
emit(OR);
match(OR);
break;
case NOT:
emit(NOT);
match(NOT);
break;
default:
assign();
}
}
static void assign()
{
switch (lookahead)
{
case TRUE:
emit(TRUE);
match(TRUE);
break;
case FALSE:
emit(FALSE);
match(FALSE);
default:
error("syntax error");
}
}
void match(int t)
{
if (lookahead == t)
{
lookahead = lexan();
}
else
error("syntax error");
}
Your immediate problem is that lookahead is already DONE if stmts() returns successfully. Calling yylex again after it hits EOF is undefined behaviour, but you really don't want to do the call because the logic is incorrect; lookahead hasn't yet been matched when stmts() returns so the caller should attempt to match it, not overwrite it with a new token.
Fixing that is the least of your problems, though. The logic of stmts and stmt are also wrong; you need to reread whatever guide/text you are using to write a recursive descent parser.
By the way, if you don't have an <<EOF>> rule, yylex will return 0 when it hits the end of input. You should consider making use of this behaviour rather than producing a custom return code.
Related
I am new to C have come across a problem that I think some of you may have had in the past. I am trying to code a program that has the user input a bunch of grades and the program tells you how many A,B,C,D,Fs you have entered.
How ever, the problem is that my counter for the grades just wont work.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include<stdint.h>
//MACRO
#define F_Range (0-49)
#define D_Range (50-59)
#define C_Range (60-69)
#define B_Range (70-79)
#define A_Range (80-100)
#define A_COUNTer
#define B_COUNTer
#define C_COUNter
#define D_COUNTer
#define F_COUNTer
//Function Prototype
void display(void);
int main(int argc, char** argv) {
{
float input, F_Counter, D_Counter, C_Counter, B_Counter, A_Counter;
printf("Total Number of grades 'A' (80-100) = %.2f",A_Counter);
//the rest of the displays would go here
do
{
fflush (stdin);
scanf("%f",&input); //Get input from user
if (input == F_Range);
{
F_Counter++;
}
if (input == D_Range);
{
D_Counter++;
}
if (input == C_Range);
{
C_Counter++;
}
if (input == B_Range);
{
B_Counter++;
}
if (input == A_Range);
{
A_Counter++;
}
}
while (input != 999);
//Exit
{
}
return 0;
}
}
ok so for start when using #define x y you simply say "change all the reference to 'x' with 'y'" so when you have
#define C_Range (60-69)
and then
if (input == C_Range );
it iterputes as
if (input == (60-69));
which makes no sense, plus you have the ";" at the end of the if statement which doesn't make sense either
instead use:
#define F_RangeLow 0
#define F_RangeHigh 49
and the if statement
if (input >= F_RangeLow && input <= F_RangeHigh )
now another thing you have to do is to initiate the counter with 0. that's because you want to stat counting from 0...
float F_Counter=0;
there is no need for 2 "{" at the start of the main
this is quite enough:
int main(int argc, char** argv) {
.
.
.
}
Your counter variables are uninitialized. So, they hold unknown values. So you have to change float input, F_Counter, D_Counter, C_Counter, B_Counter, A_Counter; to float input, F_Counter=0, D_Counter=0, C_Counter=0, B_Counter=0, A_Counter=0;
Your code has multiple major issues.
The first is that your Range macros don't expand to working code:
#define F_Range (0-49)
…
if (input == F_Range);
This expands to:
if (input == (0-49));
which is only true if input is -49. If you want to check if input is between 0 and 49, you'll have to do that explicitly:
if (input >= 0 && input <= 49)
Given your current level of understanding of C, it's probably best if you don't use macros for now. Leave them alone, write out code in full, and start using macros once you have a firm grasp of the language.
The following line:
printf("Total Number of grades 'A' (80-100) = %.2f",""A_Counter);
^^
has a stray pair of quotation marks. (Does this even compile?)
Additionally:
You've got a semicolon at the end of the if statement mentioned above, which makes it not work correctly.
Your counter variables are not initialized to zero.
float input, F_Counter, D_Counter, C_Counter, B_Counter, A_Counter;
In the main() context you are incrementing these values and none of them are initialized. You have undefined behavior when you have uninitialized vairables.
The values should be initialized like
float input =0,F_Counter=0;/* similarly for the rest */
Checking the range using the macros also needs to be fixed (0-49) doesn't mean you are checking the range from 0 to 49 . Comparison operators should be used in these cases.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdint.h>
#define S_(x) #x
#define S(x) S_(x)
#define RANGE_S(x) S((x##_Range))
#define COUNTER(x) x##_Counter
#define DISP(x) \
printf("Total Number of grades '%c' %s = %d\n",\
CHAR(x), RANGE_S(x), COUNTER(x))
#define CHECK(var, x) atoi(S(x##_Range)) <= var
#define CHAR(x) *#x
#define F_Range 0-49
#define D_Range 50-59
#define C_Range 60-69
#define B_Range 70-79
#define A_Range 80-100
void display(void);
int main(int argc, char** argv) {
float input;
int COUNTER(A)=0, COUNTER(B)=0, COUNTER(C)=0, COUNTER(D)=0, COUNTER(F)=0;
while(scanf("%f", &input)==1 && input != 999.f){
if (CHECK(input, A)){
++COUNTER(A);
} else if(CHECK(input, B)){
++COUNTER(B);
} else if(CHECK(input, C)){
++COUNTER(C);
} else if(CHECK(input, D)){
++COUNTER(D);
} else if(CHECK(input, F)){
++COUNTER(F);
}
}
DISP(A);
DISP(B);
DISP(C);
DISP(D);
DISP(F);
return 0;
}
Try Something Like This
#define F_Range(x) (x>=0 && x<=49)?true:false
#define D_Range(x) (x>=50 && x<=59)?true:false
#define C_Range(x) (x>=60 && x<=69)?true:false
#define B_Range(x) (x>=70 && x<=79)?true:false
#define A_Range(x) (x>=80 && x<=89)?true:false
AND
scanf("%f",&input); //Get input from user
if (F_Range(input));
{
F_Counter++;
}
else if (D_Range(input))
{
D_Counter++;
}
else if (C_Range(input))
{
C_Counter++;
}
else if (B_Range(input))
{
B_Counter++;
}
else if (A_Range(input))
{
A_Counter++;
}
I've write a parser for evaluating a logical expression. I know flex and bison use global variables (like yylval). I want a pure parser and a reentrant scanner for thread programming. My '.y' file is here:
%{
#include <stdio.h>
#include <string>
#define YYSTYPE bool
void yyerror(char *);
//int yylex (YYSTYPE* lvalp);
int yylex(void);
bool parseExpression(const std::string& inp);
%}
%token INTEGER
%left '&' '|'
%%
program:
program statement '\n'
| /* NULL */
;
statement:
expression { printf("%d\n", $1); return $1; }
;
expression:
INTEGER
| expression '|' expression { $$ = $1 | $3; }
| expression '&' expression { $$ = $1 & $3; }
| '(' expression ')' { $$ = $2; }
| '!' expression { $$ = !$2; }
;
%%
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
void main(void) {
std::string inp = "0|0\n";
bool nasi = parseExpression(inp);
printf("%s%d\n", "nasi ", nasi);
printf("Press ENTER to close. ");
getchar();
}
My '.y' file is here:
/* Lexer */
%{
#include "parser.tab.h"
#include <stdlib.h>
#include <string>
#define YYSTYPE bool
void yyerror(char *);
%}
%%
[0-1] {
if (strcmp(yytext, "0")==0)
{
yylval = false;
//*lvalp = false;
}
else
{
yylval = true;
//*lvalp = true;
}
return INTEGER;
}
[&|!()\n] { return *yytext; }
[ \t] ; /* skip whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
bool parseExpression(const std::string& inp)
{
yy_delete_buffer(YY_CURRENT_BUFFER);
/*Copy string into new buffer and Switch buffers*/
yy_scan_string(inp.c_str());
bool nasi = yyparse();
return nasi;
}
I've added %pure_parser to both files, changed yylex declaration to int yylex (YYSTYPE* lvalp); and replaced yylval to *lvalp, but I saw an error: 'lvalp' is undeclared identifier.. There are many examples about 'reentrant' and 'pure', but I can't find the best guideline.
Could someone guide me?
Thanks in advance.
Fortunately, I did it. Here is my code. I think it can be a good guideline for who wants write a pure parser.ل
My reentrant scanner:
/* Lexer */
%{
#include "parser.tab.h"
#include <stdlib.h>
#include <string>
#define YYSTYPE bool
void yyerror (yyscan_t yyscanner, char const *msg);
%}
%option reentrant bison-bridge
%%
[0-1] {
if (strcmp(yytext, "0")==0)
{
*yylval = false;
}
else
{
*yylval = true;
}
//yylval = atoi(yytext);
return INTEGER;
}
[&|!()\n] { return *yytext; }
[ \t] ; /* skip whitespace */
. yyerror (yyscanner, "Unknown character");
%%
int yywrap(yyscan_t yyscanner)
{
return 1;
}
bool parseExpression(const std::string& inp)
{
yyscan_t myscanner;
yylex_init(&myscanner);
struct yyguts_t * yyg = (struct yyguts_t*)myscanner;
yy_delete_buffer(YY_CURRENT_BUFFER,myscanner);
/*Copy string into new buffer and Switch buffers*/
yy_scan_string(inp.c_str(), myscanner);
bool nasi = yyparse(myscanner);
yylex_destroy(myscanner);
return nasi;
}
My pure parser:
%{
#include <stdio.h>
#include <string>
#define YYSTYPE bool
typedef void* yyscan_t;
void yyerror (yyscan_t yyscanner, char const *msg);
int yylex(YYSTYPE *yylval_param, yyscan_t yyscanner);
bool parseExpression(const std::string& inp);
%}
%define api.pure full
%lex-param {yyscan_t scanner}
%parse-param {yyscan_t scanner}
%token INTEGER
%left '&' '|'
%%
program:
program statement '\n'
| /* NULL */
;
statement:
expression { printf("%d\n", $1); return $1; }
;
expression:
INTEGER
| expression '|' expression { $$ = $1 | $3; }
| expression '&' expression { $$ = $1 & $3; }
| '(' expression ')' { $$ = $2; }
| '!' expression { $$ = !$2; }
;
%%
void yyerror (yyscan_t yyscanner, char const *msg){
fprintf(stderr, "%s\n", msg);
}
void main(void) {
std::string inp = "1|0\n";
bool nasi = parseExpression(inp);
printf("%s%d\n", "nasi ", nasi);
printf("Press ENTER to close. ");
getchar();
}
Notice that I've cheat and defined yyg myself as
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
I don't find another way to get the YY_CURRENT_BUFFER. So, If someone knows the best way to get the YY_CURRENT_BUFFER, tell me,plz.
Here is a complete Flex/Bison C++ example. Everything is reentrant, no use of global variables. Both parser/lexer are encapsulated in a class placed in a separate namespace. You can instantiate as many "interpreters" in as many threads as you want.
https://github.com/ezaquarii/bison-flex-cpp-example
Disclaimer: it's not tested on Windows, but the code should be portable with minor tweaks.
I'm having a really hard time adjusting function to my needs. First of all look at those three files and notice how I have to call f_texture function in main function in order to make it work:
externs.h
#ifndef EXTERNS_H_
#define EXTERNS_H_
extern char t_about[100];
extern int friction;
extern int f_texture(char* ,char*);
#endif
functionA.c
#include <stdio.h>
#include "externs.h"
int main()
{
f_texture("rough","friction");
printf("Friction: %d\n", friction);
f_texture("rough","t_about");
return 0;
}
functionB.c
#include "externs.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
char t_about[100];
int friction;
int f_texture(char* texture,char* what_is_needed)
{
/*Checking if both values are present*/
assert(what_is_needed);
assert(texture);
/*Static array in order to prevent it's disappearance*/
memset(t_about, '\0', sizeof(t_about));
/*Configuring variables for desired texture*/
if (strcmp(texture, "smooth") == 0)
{
strcpy(t_about, "The surface is perfectly smooth, without any "
"protuberances.\n");
friction = 0;
}
else if (strcmp(texture, "rough") == 0)
{
strcpy(t_about, "Rough bumps can be feeled under my fingertips.\n");
friction = 4;
}
/*In case of absent keyword of desired texture it will crash the program*/
else
{
assert(!what_is_needed);
}
/*Returning desired value*/
if (strcmp(what_is_needed, "t_about") == 0)
{
int i=0;
while (t_about[i] != '\0')
{
printf("%c", t_about[i]);
i++;
}
}
else if (strcmp(what_is_needed, "friction") == 0)
{
return friction;
}
/*In case of absent keyword of desired value it will crash the program*/
else
{
assert(!what_is_needed);
}
return 0;
}
And now here is my question: How to rewrite this code to make it possible to call f_texture function without using quotation marks inside? I mean instead of f_texture("abcd","efgh") just to type f_texture(abcd,efgh). I've noticed that this way it's required just after I've wrote this code.
Thanks in advance.
If you don't want to assign string constants to variables or preprocessor object macros, another option is to use preprocessor function macros, using the stringification feature:
#define call_f_texture(a,b) f_texture(#a,#b)
....
call_f_texture(rough,friction);
The C preprocessor will turn this into
f_texture("rough","friction");
You can also use some macros:
#define ROUGH "rough"
#define FRICTION "friction"
#define T_ABOUT "t_about"
int main()
{
f_texture(ROUGH, FRICTION);
printf("Friction: %d\n", friction);
f_texture(ROUGH, T_ABOUT);
return 0;
}
You can do like this,
char rough[]="rough";
char friction[]= "friction";
and call
f_texture(rough, friction);
char a[MAX] = "rouch";
char b[MAX} = "friction";
int main()
{
f_texture();
...
}
int f_texture()
{
/*Checking if both values are present*/
assert(b);
assert(a);
}
or
int f_texture(char* a,char* b)
{
/*Checking if both values are present*/
assert(b);
assert(a);
...
}
int main()
{
char a[MAX] = "rouch";
char b[MAX} = "friction";
f_texture(a,b);
...
}
I have a C program with some definitions for error codes. Like this:
#define FILE_NOT_FOUND -2
#define FILE_INVALID -3
#define INTERNAL_ERROR -4
#define ...
#define ...
Is it possible to print the name of the definition by its value? Like this:
PRINT_NAME(-2);
// output
FILE_NOT_FOUND
In short, no. The easiest way to do this would be something like so (PLEASE NOTE: this assumes that you can never have an error assigned to zero/null):
//Should really be wrapping numerical definitions in parentheses.
#define FILE_NOT_FOUND (-2)
#define FILE_INVALID (-3)
#define INTERNAL_ERROR (-4)
typdef struct {
int errorCode;
const char* errorString;
} errorType;
const errorType[] = {
{FILE_NOT_FOUND, "FILE_NOT_FOUND" },
{FILE_INVALID, "FILE_INVALID" },
{INTERNAL_ERROR, "INTERNAL_ERROR" },
{NULL, "NULL" },
};
// Now we just need a function to perform a simple search
int errorIndex(int errorValue) {
int i;
bool found = false;
for(i=0; errorType[i] != NULL; i++) {
if(errorType[i].errorCode == errorValue) {
//Found the correct error index value
found = true;
break;
}
}
if(found) {
printf("Error number: %d (%s) found at index %d",errorType[i].errorCode, errorType[i].errorString, i);
} else {
printf("Invalid error code provided!");
}
if(found) {
return i;
} else {
return -1;
}
}
Enjoy!
Additionally, if you wanted to save on typing even more, you could use a preprocessor macro to make it even neater:
#define NEW_ERROR_TYPE(ERR) {ERR, #ERR}
const errorType[] = {
NEW_ERROR_TYPE(FILE_NOT_FOUND),
NEW_ERROR_TYPE(FILE_INVALID),
NEW_ERROR_TYPE(INTERNAL_ERROR),
NEW_ERROR_TYPE(NULL)
};
Now you only have to type the macro name once, reducing the chance of typos.
You can do something like this.
#include <stdio.h>
#define FILE_NOT_FOUND -2
#define FILE_INVALID -3
#define INTERNAL_ERROR -4
const char* name(int value) {
#define NAME(ERR) case ERR: return #ERR;
switch (value) {
NAME(FILE_NOT_FOUND)
NAME(FILE_INVALID)
NAME(INTERNAL_ERROR)
}
return "unknown";
#undef NAME
}
int main() {
printf("==== %d %s %s\n", FILE_NOT_FOUND, name(FILE_NOT_FOUND), name(-2));
}
No, that's not possible. What would this print?
#define FILE_NOT_FOUND 1
#define UNIT_COST 1
#define EGGS_PER_RATCHET 1
PRINT_NAME(1);
Kinda ...
#define ERROR_CODE_1 "FILE_NOT_FOUND"
#define ERROR_CODE_2 "FILE_FOUND"
#define PRINT_NAME(N) ERROR_CODE_ ## N
or:
static char* error_codes(int err) {
static char name[256][256] = {
};
int base = .... lowest error code;
return name[err - base];
}
#define PRINT_NAME(N) error_code(N)
Why not elect to use an enumeration instead?
enum errors {FILE_NOT_FOUND = -2, FILE_INVALID = -3, INTERNAL_ERROR = -4};
FILE *fp = fopen("file.txt", "r");
if(fp == NULL) {
printf("Error\n");
exit(FILE_NOT_FOUND);
}
Not automatically. The name is losing during compilation, and only the constant number remains in the code.
But you can build something like this:
const char * a[] = {"","","FILE_NOT_FOUND","FILE_INVALID"};
and access it by using the define value absolute value as index.
Use designated initializers of C99 for this, but a bit of care is necessary if your error codes are negative.
First a version for positive values:
#define CODE(C) [C] = #C
static
char const*const codeArray[] = {
CODE(EONE),
CODE(ETWO),
CODE(ETHREE),
};
enum { maxCode = (sizeof codeArray/ sizeof codeArray[0]) };
This allocates an array with the length that you need and with the string pointers at the right positions. Note that duplicate values are allowed by the standard, the last one would be the one that is actually stored in the array.
To print an error code, you'd have to check if the index is smaller than maxCode.
If your error codes are always negative you'd just have to negate the code before printing. But it is probably a good idea to do it the other way round: have the codes to be positive and check a return value for its sign. If it is negative the error code would be the negation of the value.
This is how I do it in C:
< MyDefines.h >
#pragma once
#ifdef DECLARE_DEFINE_NAMES
// Switch-case macro for getting defines names
#define BEGIN_DEFINE_LIST const char* GetDefineName (int key) { switch (key) {
#define MY_DEFINE(name, value) case value: return #name;
#define END_DEFINE_LIST } return "Unknown"; }
#else
// Macros for declaring defines
#define BEGIN_COMMAND_LIST /* nothing */
#define MY_DEFINE(name, value) static const int name = value;
#define END_COMMAND_LIST /* nothing */
#endif
// Declare your defines
BEGIN_DEFINE_LIST
MY_DEFINE(SUCCEEDED, 0)
MY_DEFINE(FAILED, -1)
MY_DEFINE(FILE_NOT_FOUND, -2)
MY_DEFINE(INVALID_FILE, -3)
MY_DEFINE(INTERNAL_ERROR -4)
etc...
END_DEFINE_LIST
< MyDefineInfo.h >
#pragma once
const char* GetDefineName(int key);
< MyDefineInfo.c >
#define DECLARE_DEFINE_NAMES
#include "MyDefines.h"
Now, you can use the declared switch-case macro wherever like this:
< WhereEver.c >
#include "MyDefines.h"
#include "MyDefineInfo.h"
void PrintThings()
{
Print(GetDefineName(SUCCEEDED));
Print(GetDefineName(INTERNAL_ERROR));
Print(GetDefineName(-1);
// etc.
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does VS2010 give syntax errors when syntax is correct?
I'm trying to develop a kind of Windows 32 service in C language, using Visual Studio 2010.
I created a new project, and inserted .c files :
main.c
service.c
misc.c
I also have two header files :
myerrors.h
my.h
Here's the code I have (be aware that it's just a draft).
main.c :
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "stdafx.h"
#include "my.h"
#include "myerrors.h"
static int parse_args(int ac, char **av)
{
int i = 0;
while (++i < ac)
if (strcmp(av[i], "-i") && !InstallMyService())
return false;
else if (strcmp(av[i], "-d") && !UninstallMyService())
return false;
else if (strcmp(av[i], "-p"))
if (!av[i + 1])
return false;
else
{
if (!InsertPathInRegistry(av[i + 1]))
return false;
i++;
}
else
return false;
return true;
}
int main(int ac, char **av)
{
HANDLE hLogFile;
if ((hLogFile = CreateFile(LOG_FILE_PATH, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
aff_error(CANT_CREATE_FILE);
if (ac > 1)
{
if (!parse_args(ac, av))
{
aff_error(BAD_ARGUMENTS);
return EXIT_FAILURE;
}
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[] = {{DC_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
getchar();
if (!CloseHandle(hLogFile))
aff_error(CLOSE_FILE_FAILED);
return EXIT_SUCCESS;
}
misc.c :
#include <Windows.h>
#include <stdio.h>
#include "my.h"
#include "myerrors.h"
void aff_error(char *error_str)
{
fprintf(stderr, "ERROR: %s\n", error_str);
}
bool InsertPathInRegistry(char *path)
{
printf("LOG: Inserting %s as ", path);
}
void WriteInLogFile(HANDLE hLogFile, char *log_string)
{
printf("WriteInLogFile function");
}
service.c :
#include <Windows.h>
#include "my.h"
bool InstallMyService()
{
return true;
}
bool UninstallMyService()
{
return true;
}
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
}
void WINAPI ServiceMain(DWORD ac, LPTSTR *av)
{
}
My headers are just some function declarations and macros such as :
# define DC_SERVICE_NAME "MyService"
/* MISC functions */
void aff_error(char *error_str);
my.h
#ifndef _MY_H_
# define _MY_H_
#include <Windows.h>
#include <strsafe.h>
/* Macros */
# define LOG_FILE_PATH "c:\\my_log_file.txt"
# define DC_SERVICE_NAME "MyService"
/* MISC functions */
void aff_error(char *error_str);
/* SERVICE functions */
void WINAPI ServiceMain(DWORD ac, LPTSTR *av);
bool InstallMyService();
bool UninstallMyService();
bool InsertPathInRegistry(char *path);
void WINAPI ServiceCtrlHandler(DWORD Opcode);
#endif /*!MY_H_ */
While trying to compile the project, i got some weird errors :
my.h(19): error C2061: syntax error : identifier 'InstallMyService'
my.h(19): error C2059: syntax error : ';'
my.h(19): error C2059: syntax error : ')'
Or :
my.h(21): error C2061: syntax error : identifier 'InsertPathInRegistry'
my.h(21): error C2059: syntax error : ';'
my.h(21): error C2059: syntax error : 'type'
I checked on some forums that says those errors are commonly errors with includes badly placed, but I don't really know in this case, I don't think I made mistakes with includes...
Can anyone illuminate me ?
Thanks.
bool is not a data type in ANSI C. It is a data type in the C99 version of the language, only if <stdbool.h> is included, but Visual Studio does not support C99, only C89 (C99 also adds the _Bool data type, which can be used without including any headers).
I suggest you replace bool with another type such as int, or use a typedef to alias it with int or unsigned char or something.