Objective-c main routine, what is: int argc, const char * argv[] - objective-c

What are the arguments passed into the main method of a command-line program:
int main(int argc, const char * argv[])
what is the first int mean?
And what is the 2nd parameter, is that an array of chars?
How would one use these?
Also, what practical use is a command-line project type, other than using it to learn obj-c i.e. to practise.

argc means "argument count". It signifies how many arguments are being passed into the executable.
argv means "argument values". It is a pointer to an array of characters. Or to think about it in another way, it is an array of C strings (since C strings are just arrays of characters).
So if you have a program "foo" and execute it like this:
foo -bar baz -theAnswer 42
Then in your main() function, argc will be 5, and argv will be:
argv[0] = "/full/path/to/foo";
argv[1] = "-bar";
argv[2] = "baz";
argv[3] = "-theAnswer";
argv[4] = "42";

The parameters to main() are a unix convention for accessing the arguments given on the command line when your program is executed. In a Cocoa app, you can access them the plain old C way, or you can use NSProcessInfo's -arguments method to get them in an NSArray of NSString objects, or use NSUserDefaults to get them as values in a dictionary.

Just to add to the other answers - Objective-C targets both OS X and iOS. And while there is not much value in iOS command line applications, the shell on OS X is still widely used and there are lot of people writing command line tools.

That main is from C and not specific to objective-c. Argc gives you the number of command line arguments passed to your C program. Argv is an array of C strings and contains the command line arguments.
You would use them and the command-line project any time you wanted to write a command line tool or a program you interact with from the command line.

As wikipedia (and any other source says):
int main(void)
int main(int argc, char *argv[])
The parameters argc, argument count, and argv, argument vector, respectively give the number and value of the program's command-line arguments. The names of argc and argv may be any valid identifier in C, but it is common convention to use these names. In C++, the names are to be taken literally, and the "void" in the parameter list is to be omitted, if strict conformance is desired. Other platform-dependent formats are also allowed by the C and C++ standards, except that in C++ the return type must stay int; for example, Unix (though not POSIX.1) and Microsoft Windows have a third argument giving the program's environment, otherwise accessible through getenv in stdlib.h:
int main(int argc, char **argv, char **envp)

Also, what practical use is a command-line project type, other than using it to learn obj-c i.e. to practise.
The practical use is creating a command-line tool using code from a Framework or Application that you have written. Helpers, utilities, launch agents and daemons, all of these background processes are typically implemented as command-line tools.

Related

Why can't I use yytext inside yyerror (Yacc)

Im having some trouble with my analizer. I.m trying to use yytext inside my yyerror but it shows me this error, can you help me?
You can't use yytext in your parser because it is defined by the lexer.
Indeed, you normally shouldn't use yytext in your parser because its value is not meaningful to the parse. Your attempt to use it to provide context in error messages is just about the only reasonable use, and even then there is a certain ambiguity because you can't tell whether the erroneous token is the one currently in yytext or the previous token, which was overwritten when the parser obtained its lookahead token.
In any case, if you want to refer to yytext inside your parser, you'll need to declare it, which will normally require putting
extern char* yytext;
into your bison grammar file. Since the only place you can reasonably use yytext is yyerror, you might change the definition of that function to:
void yyerror(const char* msg) {
extern char* yytext;
fprintf(stderr, "%s at line %d near '%s'\n", msg, nLineas, yytext);
}
Note that you can get flex to track line numbers automatically, so you don't need to track your own nLineas variable. Just add
%option yylineno
at the top of your flex file, and the global variable yylineno will automatically be maintained during lexical analysis. If you want to use yylineno in your parser, you'll need to add an an extern declaration for it as well:
extern int yylineno;
Again, using yylineno in the parser may be imprecise because it might refer to the line number of the token following the error, which might be on a different line from the error (and might even be separated from the error by many lines of comments).
As an alternative to using external declarations of yytext and yylineno, you are free to put the implementation of yyerror inside the scanner definition instead of the grammar definition. Your grammar file should already have a forward declaration of yyerror, so it doesn't matter which file it's placed in. If you put it into the scanner file, global scanner variables will already be declared.

Ignore comma inside #define macro call

I created a special console log function macro. It works successfully except when there's a comma in the parameter, even if it's part of another expression, i.e. not another argument. I think it's due to the fact that macros are expanded at the pre-processing stage, so the semantic analysis hasn't occurred yet to understand that the comma is not another argument. Here is what I mean:
#define FANCY_LOG(message) [MyLogger logDebug:message withClassAndMethodName: __PRETTY_FUNCTION__ lineNumber: __LINE__];
+(BOOL)logDebug:(NSString *)message withClassAndMethodName:(const char *)name lineNumber:(int)lineNumber;
These work:
FANCY_LOG(#"Hello world");
FANCY_LOG([NSString stringWithFormat:#"Hello!"]);
This does not work:
FANCY_LOG([NSString stringWithFormat:#"Hello %#!", planet]);
Although the comma obviously is part of the NSString expression, the macro interprets it as another argument, I get the following error:
Too many arguments provided to function-like macro invocation
Here's what I have tried unsuccessfully (and variants of these):
#define FANCY_LOG(...) [MyLogger logDebug:##__VA_ARGS___ withClassAndMethodName: __PRETTY_FUNCTION__ lineNumber: __LINE__];
#define FANCY_LOG(message) [MyLogger logDebug:#message withClassAndMethodName: __PRETTY_FUNCTION__ lineNumber: __LINE__];
You are doing that wrong. First of all there are lots of great ready solutions so you do not have reinvent the wheel (don't remember for sure but I think CocoaLumberjack is best).
And your logger can look like this (I've got rusty with Objective C):
+(void) function:(char *)methodName
inLine:(int)line
logs:(NSString *)format, ...;
...
#define FANCY_LOG(...) [MyLogger function: __PRETTY_FUNCTION__ \
inLine: __LINE__ \
logs: __VA_ARGS__]
// then usage:
FANCY_LOG(#"Hello %#!", planet);

Xcode - replace function with regex and two-digit capture group (back reference)

I would like to use the Xcode's find in project option to normalize the signatures of methods.
I wrote the find expression:
^\s*([+-])\s*\((\w+)\s*(\*?)\s*\)\s*(\w+)(\s*(:)\s*(\()\s*(\w+)\s*(\*?)\s*(\))\s*(\w+))?
and the replacement expression:
\1 \(\2\3\)\4\6\7\8\9\10\11
The test string is:
+(NSString *) testFunction : (NSInteger ) arg1
and the desired result:
+ (NSString*)testFunction:(NSInteger)arg1
Unfortunatelly Xcode isn't able to recognize te two digit capture group \10 and translates it to \1 and '0' character and so long. How to solve this problem or bug?
Thanks in advance,
MichaƂ
I believe #trojanfoe is correct; regexes can only have nine capture groups. This is waaay more than you need for your particular example, though.
^\s*([+-])\s*\((\w+)\s*(\*?)\s*\)\s*(\w+)(\s*(:)\s*(\()\s*(\w+)\s*(\*?)\s*(\))\s*(\w+))?
\1 \(\2\3\)\4\6\7\8\9\10\11
The first thing I notice is that you're not using \5, so there's no reason to capture it at all. Next, I notice that \6 corresponds to the regex (:), so you can avoid capturing it and replace \6 with : in the output. \7 corresponds to (\(), so you can replace \7 with ( in the output. ...Iterating this approach yields a much simpler pair of regexes: one for zero-argument methods and one for one-argument methods.
^\s*([+-])\s*\((\w+)\s*(\*?)\s*\)\s*(\w+)
\1 \(\2\3\)\4
^([+-] \(\w+\*?\)\w+)\s*:\s*\(\s*(\w+)\s*(\*?)\s*\)\s*(\w+)
\1:\(\2\3\)\4
Notice that I can capture the whole regex [+-] \(\w+\*?\)\w+ without all those noisy \s*s, because it's been normalized already by the first regex's pass.
However, this whole idea is a huge mistake. Consider the following Objective-C method declarations:
-(const char *)toString;
-(id)initWithA: (A) a andB: (B) b andC: (C) c;
-(NSObject **)pointerptr;
-(void)performBlock: (void (^)(void)) block;
-(id)stringWithFormat: (const char *) fmt, ...;
None of these are going to be parsed correctly by your regex. The first one contains a two-word type const char instead of a single word; the second has more than one parameter; the third has a double pointer; the fourth has a very complicated type instead of a single word; and the fifth has not only const char but a variadic argument list. I could go on, through out parameters and arrays and __attribute__ syntax, but surely you're beginning to see why regexes are a bad match for this problem.
What you're really looking for is an indent program (named after GNU indent, which unfortunately doesn't do Objective-C). The best-known and best-supported Objective-C indent program is called uncrustify; get it here.

ATI OpenCL printf extension issue with char* argument passed to a function

I use OpenCL on an ATI card with the printf extension enabled. I've written a function to print out variables:
void printVar(constant char* name, float var)
{
printf("%s: %f\r\n", name, var);
}
This code works as expected when compiled as plain C, but if i invoke it in OpenCL with
printVar("foo", 0.123);
the result is always some random char followed by 0.123 instead of "foo: 0.123". I guess the compiler has problems with recognizing the char* string, is there a workaround or a fix so i can get the function working?
As I mentioned in my comment I also get the same behavior, however I can suggest a simple workaround for the use case you showed, I.e. when the string is known at compile time we could just use a define statement instead:
#define PRINTVAR(N,X) (printf(N ": %f\r\n", X))

How to program Lex and Yacc to parse a partial file

Let me tell with an example.
Suppose the contents of a text file are as follows:
function fun1 {
int a, b, c;
function fun2 {
int d, e;
char f g;
function fun3 {
int h, i;
}
}
In the above text file, the number of opening braces are not matching the number of closing braces. The file as a whole doesn't follow the syntax. However the partial functions fun2 and fun3 follows the syntax. Typically the text file is very large.
If the user wants to parse the entire file ie function fun1, then the program should output an error as the braces are not matching. However, if the user wants to parse only the partial file ie function fun2/fun3, then the program shouldn't throw out an error as the braces are matching.
I have a question now
1. Is there a way to let the Lex and Yacc load only a
partial file ? If so then how it needs to be done.
Are you using bison/flex or plain old yacc/lex ?
It's a long time I played with yacc.
The technical answer is different for both pair of tool.
With flex you'll have to deal with the buffer mechanism.
The final code will be cleaner.
With lex you'll have to do all by hand.
At least you have to redefine input and unput macro.
You can also try to play with yyin and fseek.
On the parser side you'll have to deal with error management (yyerrok macro) and error token
http://dinosaur.compilertools.net/bison/bison_9.html#SEC81