I've been trying to figure out what's wrong with this code without success for a while:
#include"ec.h"
#include"pantalla.h"
#include"so.h"
#define NPROC 20
WORD flags;
void (*rsi_ck)();
char idproces = 'a';
tPCB *pRUN, *pRDY;
tPCB pcbs[NPROC];
char arterisc[]="|/-\\";
void crearProces (tcpb *pcb,PTR funcio)
{
pcb->IdProces = (int) idproces;
a=a+1;
pcb->Estat = RDY;
pcb->Flags = flags;
pcb->CS = Segment(funcio);
pcb->IP = Desplacament(funcio);
pcb->SS_SP =(long)(&(pcb->Pila[MIDA_PILA-12]));
pcb->Pila[MIDA_PILA-11]=Segment(&pRUN);
pcb->Pila[MIDA_PILA-1]=512;
pcb->Pila[MIDA_PILA-2]=pcb->CS;
pcb->Pila[MIDA_PILA-3]=pcb->IP;
}
//more lines below
It gives me a compilation error, ", expected" on line 16, where the function "CrearProces" is defined. I've tried to move the definition of the function to any other line and the error just "follows" it.
Thanks in advance.
Edit: tPCB is defined as follows:
typedef struct
{
LONG IdProces;
WORD Estat;
LONG SS_SP;
WORD Quantum;
WORD Prioritat;
WORD Flags;
WORD CS;
WORD IP;
WORD Pila[MIDA_PILA];
} tPCB;
What's a "tcpb" in void crearProces (tcpb *pcb,PTR funcio)? Should it be a tPCB?
For historical reasons C language supports two styles of function declarations (and definitions).
The "new" prototype-based style
void foo(int a, short b, double c)
{
...
And the "old" K&R style
void foo(a, b, c)
int a;
short b;
double c;
{
...
When the compiler sees that the first identifier in () is a known type name, it assumes that the function is defined with prototype. When the compiler sees that the first identifier in () is not a known type name, it assumes that the function is defined in old K&R style. In the latter case each identifier must be separated from the next one by ,.
In your case the function definition has tcpb as the first identifier in (). Apparently there's no such type in your program, which makes the compiler to assume that this is not a type name but rather a parameter name in a K&R style definition. As such it must be followed by a ,.
This is obviously not your intent.
So, what is tcpb? Why are you using it as a type name when there's no such type in your program?
P.S. Different compilers can use different approaches to recognize invalid code. For that reason, they can detect the same error differently and issue different diagnostic messages. Apparently your specific compiler is using the logic I described above. Hence the error message about a comma. Another compiler might report the same error differently.
Related
Implicit cast from short* to int* prints the warning about incompatible pointer type (and I understand why).
Implicit cast from enum* to int* prints same warnig.
There's a tool snacc that generates the following code:
typedef enum
{
CHARGINGCALLING = 0,
CHARGINGCALLED = 1,
NONECHARGING = 2
} ChargedParty; /* ENUMERATED { CHARGINGCALLING (0), CHARGINGCALLED (1), NONECHARGING (2) } */
typedef struct MSOriginatingSMSinSMS_IWMSC /* SET */
{
ChargedParty* chargedParty; /* [6] IMPLICIT ChargedParty OPTIONAL */
} MSOriginatingSMSinSMS_IWMSC;
#define BEncChargedPartyContent BEncAsnEnumContent
int BEncMSOriginatingSMSinSMS_IWMSCContent (BUF_TYPE b, MSOriginatingSMSinSMS_IWMSC *v) {
BEncChargedPartyContent (b, (v->chargedParty));
...
}
A header file shipped with this tool:
int BEncAsnIntContent (BUF_TYPE b, int *data);
#define BEncAsnEnumContent BEncAsnIntContent
The call to BEncChargedPartyContent prints the warning.
Can I modify the declaration of BEncAsnEnumContent so it accepts without a warning pointers to any enum, but not void* or short*?
Of course using sed I could replace the macro BEncChargedPartyContent with a static function:
static AsnLen BEncChargedPartyContent (BUF_TYPE b, ChargedParty *data)
{
return BEncAsnEnumContent(b, (int*)data);
}
But there're too many of them.
Your own proposal with a static function sounds not so bad.
Can I modify the declaration of BEncAsnEnumContent so it
accepts without a warning pointers to any enum, but not
void* or short*?
If you want, you can use a static assertion as John Zwinck hinted at.
#define BEncAsnEnumContent(b, d) ({\
_Static_assert(sizeof(int) == sizeof *(d), "wrong data size");\
BEncAsnIntContent(b, (int *)d); })
What you think of in your comment below is a viable alternative with the advantage that it allows enumerations of different sizes; this is how I understand what you mean:
#define BEncAsnEnumContent(b, d) MyEncAsnEnumContent(b, *(d))
static int MyEncAsnEnumContent(BUF_TYPE b, int val)
{
return BEncAsnIntContent(b, &val);
}
The enumeration constants, that is the list of values in your enum declaration, are guaranteed to be of type int. However, this does not apply to the enum variable itself. An enum need not be compatible with int nor with another, different enum type variable. The size can vary from case to case and from compiler to compiler.
This is the root of the problem. If you mix enum and int, or two different enums with each other, all is fine if they have the same size. They are then compatible and you can convert pointers from one of the types to the other without problems.
However, if they are not of the same size, you cannot do this. It would give incompatible types: you would violate the strict aliasing rule and there might also be alignment issues. Plus the obvious: if you try to read a large chunk of data from a location where only a small chunk of data is stored, there's no telling what you will end up with.
The reliable solution is to change your function to simply use an integer type instead of a pointer:
int BEncAsnIntContent (BUF_TYPE b, int data);
There doesn't seem to be a reason why they pass the parameter through a pointer in the first place. Keep it simple.
From my memory, mangling name is not used in C, which is kinda of a feature that we take advantage using C function for ABI (Application Binary Interface). But recently I have been reading this article about mangling name in C
https://gustedt.wordpress.com/2011/06/24/name-mangling-in-c/
Question here is, If in any case that compiler will mangle C function name?
Since C is a programming language that does not support name function overloading, it does no name mangling. But for compilers targeted at Microsoft Windows Platform, which has a variety of calling conventions like _cdecl,_stdcall etc. the function names are mangled to provide information regarding the calling convention.
For example,
int _stdcall fun(int myVar) {return 0;}
int _fastcall fun(int myVar){return 1;}
int _cdecl fun(int myVar){return 2;}
the compiler(32-bit) output will be like this:
_fun#4 /* _(function_name)#(argument_size_in_bytes) */
#fun#4 /* #(function_name)#(argument_size_in_bytes) */
_fun /* _(function_name) */
Function names won't be mangled, except apparently in the case of Unicode identifiers. For example:
// Mangled as "o_u03ba" using Intel's compiler "icc").
extern int o\u03ba(void);
The issue with icc highlighted by the blog article linked in the question is obviously a problem when the compiler generates non-unique symbol names:
//Both will have the same symbol name.
extern void o\u03ba(volatile int *p)
{
*p = -32767;
}
extern void o_u03ba(volatile int *p)
{
*p = 0;
}
...
volatile int n;
// Should print -32767; may print 0 or -32767.
o\u03ba(&n);
printf("%d\n", n);
// Should print 0; will print the same thing as the previous line.
o_u03ba(&n);
printf("%d\n", n);
Functions declared with the static keyword have internal linkage. Despite this, the compiler's internal representation may still use a mangled name, though you will never see it in the resulting program. When resolving references to functions, however, the code presented by the article indicates that even using the name at all can cause an issue:
static void foo\u03ba(volatile int n)
{
printf("foo\\u03ba: n = %d\n", n);
}
static void foo_u03ba(volatile int n)
{
printf("foo_u03ba: n = %d\n", n);
}
...
volatile int n = 10;
// These two lines may print the same thing.
foo\u03ba(n);
foo_u03ba(n);
Since you technically cannot take the address of a function and print it reliably, the best you can do is uniquely identify which function is called.
I was reading "Compiler Design in C" book. In the basics section I found a c snippet for lexer something like this -
static int Lookahead = -1;
int match(token)
int token;
{
if(Lookahead == -1)
Lookahead = lex();
return token == Lookahead;
}
void advance(){
Lookahead = lex();
}
I got confuse about how this match function get compiled on gnu gcc. So I wrote a function that looks like
int a(token)
int token;
{
printf("Value of token is %d", token);
}
int main()
{
printf("Hello world!\n");
a(1);
return 0;
}
And I am getting following output-
Hello world!
Value of token is 1
But I dont getting the reason behind that function declaration. What the benefit of declaring function this way? And how the value of token being 1? Why its not a compile error? Is it some kind of function declaration in C?
Thanks for checking my question. Any kind of help will be great.
Its an old and deprecated K&R style of function declaration.
int match(token)
int token;
{
// Function body
}
is equivalent to
int match(int token)
{
// Function body
}
except that in former, compiler would not check that the function is called with the right number of arguments nor will it check the types of arguments. It rely on default argument promotions.
C89 and C99 support this style too.
This is the original way that C functions used to be declared when Kernighan and Ritchie first developed the C programming language. It is referred to as 'K&R C'
C went through a standardisation process and this form of function declaration was changed to the one that you are used to.
On the page http://en.wikipedia.org/wiki/The_C_Programming_Language the first edition of the book would have had the old style function declarations, I think it was dropped in the second edition.
Function definitions in the original K&R C were simpler. In your example, the type declaration for function parameter token is actually redundant. The code could be simplified this way:
static int Lookahead = -1;
int match(token) {
if (Lookahead == -1)
Lookahead = lex();
return token == Lookahead;
}
void advance(){
Lookahead = lex();
}
Indeed the function return type and variable types also defaulted to int, void was not yet invented, the return statement was optional... leading to further simplification:
static Lookahead=-1;
match(token){
if(Lookahead==-1) Lookahead=lex();
return token==Lookahead;
}
advance(){Lookahead=lex();}
Such primitive style was more compact, but was quite error prone and is no longer supported by modern conforming compilers. The function definition syntax in your example is still supported, but considered obsolete and likely to disappear at some point.
I keep getting this error:
C2055 error - expected formal parameter list, not a type list
I know what it means; I read about it on the Internet, yet I don't understand why I keep getting it. The part of my code that triggers the error (the file is called other_funcs.c):
#include "main_funcs.h"
#include "other_funcs.h"
void addWord(sWord **first) //line #4
{
sWord *after;
char *input_string, *part;
const char seperator[4] = "_#_";
/.......bla bla.... more code.../
sWord is a struct. The error is:
1>d:\cs - exercises\ex5\backup\new folder\other_funcs.c(4): error C2055: expected formal parameter list, not a type list
I don't know if this is necessary, but the header file with the the addWord() function is called other_funcs.h:
#ifndef OTHER_FUNCS_H
#define OTHER_FUNCS_H
void addWord(sWord**);
char *inputString();
int badInput(char*);
void removeWord(sWord**);
int checkYear(sWord*, unsigned short);
int my_strlen(char*);
int countDist(char*, char*);
int new_alreadyThere(sWord*, char*)
#endif
When you get a truly weird compiler error, look at the preceding line.
In this case (ignoring whitespace and preprocessor directives), it's this, from the header file.
int new_alreadyThere(sWord*, char*)
You're missing a semicolon at the end of it.
You're missing a semicolon on the last line of the header file.
This confuses the compiler when it tries to parse the next line.
// K&R syntax
int foo(a, p)
int a;
char *p;
{
return 0;
}
// ANSI syntax
int foo(int a, char *p)
{
return 0;
}
As you see, in K&R style, the types of variables are declared in new lines instead of in the braces. How to convert a K&R function declaration to an ANSI function declaration automatically? Does anybody know such an easy-to-use tool in Linux?
You can use cproto or protoize (part of GCC) to generate function prototypes or convert old style (K&R) functions to ANSI format.
Since You wanna convert a multiline string, you chould consider perl
you have
void old_style( c , a ) char c; int a; { /* some multiline code */ }
and must have
void old_style( char c, int a) {}
So
perl -i.bkp -nle 's/\((void|int|char|float|long) [a-zA-Z0-9_-]*\)([a-zA-Z0-9_-] ?,[a-zA-Z0-9_-] ?)\(.*{\)/\1(\2)/g'
or something like it, would do the trick.
It would be easier to tackle down the correct regex to this if you try it out and post in comments the output of
diff file.c file.c.bkp
for each of your source files.
if you want to create standard C prototypes for a .h file use mkproto.c
mkproto thisoldfile.c > thisoldfile.h
You then could also paste over the old K&R code in the C file definition if desired.
Another answer by Robert contained the following (useful) information before it was deleted for being a 'link-only' answer:
You can find mkproto.c at:
https://www.pcorner.com/list/C
There are plenty of other utilities there.
The site hosts two versions of "mkproto" — MKPROTO.ZIP dated 1989-09-07 and MKPROTOB.ZIP dated 1992-06-27. You have to register with the host site, The Programmer's Corner, to download the files. The files appear about 2/3 of the way down a long page of possible downloads.
My gcc installation had neither cproto nor mkproto. But I did have Vim and I figured out a global substitute to do this one parameter at a time...
:%s/^\(\%(\w\+\%(\s*\*\+\s*\|\s\+\)\)\+\)\(\w\+\)\s*(\#=\(.\{-}\)\([(,)]\)\s*\(\w\+\)\s*\([,)].*\)\n\s*\(.\{-}\)\5\([^;]*\);/\1\2\3\4\7\5\8\6/
where the recorded subexpressions are:
the function return type
the function name
the already-prototyped parameters (if any)
the delimiter before the next K&R parameter to fix - '(' or ','
the next K&R parameter to fix
the following delimiter - ',' or ')' followed by any remaining (unprocessed) K&R parameter identifiers and closing ')'
the parameter's type
the parameter's post-identifier characters (e.g., brackets)
Repeat until no more matches in the file. Note, the pattern presumes the K&R function declaration is on one line, followed by individual parameter declarations on successive lines.
Two applications of this substitute successfully processes:
int main(argc,argv)
int argc;
char *argv[];
{
printf("Hello world!\n");
return 0;
}
into:
int main(int argc,char *argv[])
{
printf("Hello world!\n");
return 0;
}