Help needed to count lines between preprocessor directives

N

Nalla

Hi,
I want a program. It should be a command line one. you can input the
path of a folder(preferably) or a file...it should count the no. of
lines between the compiler directives,
ifdef win32 and # endif.can u pls help me out...
 
R

rzed

Nalla said:
Hi,
I want a program. It should be a command line one. you can input
the path of a folder(preferably) or a file...it should count the
no. of lines between the compiler directives,
ifdef win32 and # endif.can u pls help me out...

Glad to.

Write a program that accepts arguments from the command line. Decide
what to do with input that doesn't make sense in terms of your
assignment, and write the code to do that.

For valid input, which will, I assume, be the name of a file that
contains at least one compiler directive, open the file. If it opens
correctly, read it one line at a time and determine whether the line
contains a compiler directive. If it does, begin counting with the
next line. When you reach the next compiler directive, emit a message
that tells you how many lines you have counted, and prepare to start
counting again. Continue until you run out of lines. Decide how you
will handle reporting on the last set of lines (if there are any after
the last compiler directive). Close the file. Emit any concluding
messages you think appropriate.

I can attest that I am writing this on a machine running Windows 2000.

Hope that helps.

Here's some code (untested):


#include <stdlib.h>

int main( int argc, char * argv[] )
{

/* do the stuff I talked about */

return EXIT_SUCCESS;
}
 
J

Jens.Toerring

Nalla said:
I want a program. It should be a command line one. you can input the
path of a folder(preferably) or a file...it should count the no. of
lines between the compiler directives,
ifdef win32 and # endif.can u pls help me out...

Sorry, but clc is neither alt.source.wanted nor has your question
anything to do with C.

<OT>
Since I feel like being nice today here's an (completely untested!)
Perl script (I don't know what you mean by "path of folder" because
a folder rarely has lines in it. and even less compiler directives.
I also would usually try to avoid doing something like this in C
because I am too lazy or got better things to do):

#!/usr/bin/perl -w

use strict;

my $f;
my ( $level, $lc, $found, $in_sec ) = ( 0, 0, 0, 0 );

open( $f, "<$ARGV[ 0 ]" ) or die "Can't open file $ARGV[ 0 ]: $!\n";

while ( <$f> ) {
if ( /\s*#endif\s*/ ) {
$level-- ;
die "More \"#endif\" than \"#ifxxx\" found in file $ARGV[ 0 ]\n"
if $level < 0;
$in_sec = 0;
}
$lc++ if $in_sec;
if ( /\s*#if\s+win32\s*/ ) {
$found++;
$in_sec = 1;
}
$level++ if /\s*#if/;
}

die "Missing #endif in file $ARGV[ 0 ]\n" unless ! $level;
if ( $lc ) {
print "Found $lc lines between \"#if win32\" and the corresponding " .
"\"#endif\" directives (in $found sections)\n";
} else {
print "No \"#if win32\" directive found in file $ARGV[ 0 ]\n";
}

Not counting continuation lines is left as an exercise for the reader ;-)
</OT>
Regards, Jens
--
_ _____ _____
| ||_ _||_ _| (e-mail address removed)-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring
 
M

Malcolm

Nalla said:
I want a program. It should be a command line one. you can input the
path of a folder(preferably) or a file...it should count the no. of
lines between the compiler directives,
ifdef win32 and # endif.can u pls help me out...
Unfortunately none of the regs are likely to have time to offer a free
programming service.
However your problem shouldn't be too difficult, particularly if you are not
too fussy about being robust for degenerate cases such as preprocessor
directives being themselves redefined or placed in comments.

C offers no directory services so to do a whole folder at once you need a
platform-specific extension.

Simply open the file, read in the lines one at a time, and search for #ifdef
win32.
Then search though counting #if... s and #endifs, until you come to the
matching #endif.
 
M

Mike Wahler

Nalla said:
Hi,
I want a program. It should be a command line one. you can input the
path of a folder(preferably) or a file...it should count the no. of
lines between the compiler directives,
ifdef win32 and # endif.can u pls help me out...

Since we don't do people's work for them here, I'll offer
a more general solution that you should be able to adapt
to your specific needs. This shows the line number where
each directive appears (and the line itself), and how many
lines appear between successive directives. A directive is
considered to exist on any line whose first non-whitespace
character is a '#' character.



#define COMPILE_THIS


#ifdef COMPILE_THIS

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

#define LINE_SIZE 128
#define DIRECTIVE_CHAR '#'

int is_directive(const char *line, size_t len)
{
static char tok[LINE_SIZE];
return sscanf(line, "%s", tok) != EOF &&
*tok == DIRECTIVE_CHAR;
}

int main(int argc, char **argv)
{
char line[512] = {0};
size_t line_no = 0;
size_t between = 0;
FILE *input = NULL;

if(argc < 2)
{
puts("Requires file name argument");
return EXIT_FAILURE;
}

if(!(input = fopen(argv[1], "r")))
{
puts("Cannot open input\n");
return EXIT_FAILURE;
}

while(fgets(line, sizeof line, input))
{
++line_no;

if(is_directive(line, sizeof line))
{
if(between)
printf("[%lu line%c]\n",
(unsigned long)between, " s"[between > 1]);

printf("[Line %lu] %s", (unsigned long)line_no, line);
between = 0;
}
else
++between;
}

fclose(input);
return 0;
}

#endif



Output when given its own source:

[Line 1] #define COMPILE_THIS
[2 lines]
[Line 4] #ifdef COMPILE_THIS
[1 line ]
[Line 6] #include <stdio.h>
[Line 7] #include <stdlib.h>
[Line 8] #include <string.h>
[1 line ]
[Line 10] #define LINE_SIZE 128
[Line 11] #define DIRECTIVE_CHAR '#'
[48 lines]
[Line 60] #endif


I did not test this thoroughly; I'll let you discover
and fix any bugs that might exist. :)

HTH,
-Mike
 
M

Mike Wahler

[snip]
int main(int argc, char **argv)
{
char line[512] = {0};

Oops, forgot to change all my 'hardcodes' to #defined values.
Make that:

char line[LINE_SIZE] = {0};

[snip]

Sorry about that.

-Mike
 
R

richard

Glad to.

Write a program that accepts arguments from the command line. Decide
what to do with input that doesn't make sense in terms of your
assignment, and write the code to do that.
LOL!

Hope that helps.

It does. I feel much better after reading your post.
Here's some code (untested):


#include <stdlib.h>

int main( int argc, char * argv[] )
{

/* do the stuff I talked about */

return EXIT_SUCCESS;
}

I got warning message about unused parameters argc and argv, but otherwise
worked perfectly in my tests.
 
M

MikeyD

Nalla said:
Hi,
I want a program. It should be a command line one. you can input the
path of a folder(preferably) or a file...it should count the no. of
lines between the compiler directives,
ifdef win32 and # endif.can u pls help me out...

Not robust or anything, but should work...
#include <stdio.h>
char filepath[100];
char tstr[10];
int lines;
FILE* cfile
int main(void){
lines=0
printf("OK, so what's the file then?\n");
gets(filepath);
cfile=fopen(filepath, "r");
fseek(cfile,SEEK_SET);//not sure if this is correctly formulated
for(;strcmp(tstr,"#ifdef win32")!=0;fgets(cfile,tstr));//value for strcmp
may be wrong, fgets args may also be wrong
for(;strcmp(tstr,"#endif")!=0;fgets(cfile,tstr)) lines++;
printf("There were %d lines between the pre-processor commands\n",lines);
//is this how you want it returned?
return lines; //or return 0;
}
 
M

Martin Ambuhl

MikeyD said:
Not robust or anything, but should work...

And is grossly antisocial. The lack of indentation and the gratuitous use
of filescope variables, and '//' comments on very long lines suggests that
yours is a joke post (but not a very good one). Be that as it may,
gets(filepath);
is a terrible thing to suggest. Not even the most clueless poster deserves
to be treated that way.
 
L

LibraryUser

Mike said:
.... snip ...

lines appear between successive directives. A directive is
considered to exist on any line whose first non-whitespace
character is a '#' character.

#define whatsit "I am a \
# marker containing string "
 
M

Mike Wahler

LibraryUser said:
#define whatsit "I am a \
# marker containing string "

OK, you broke my toy program. When someone pays me,
I'll make it better. :)

-Mike
 
M

MikeyD

Not robust or anything, but should work...
And is grossly antisocial. The lack of indentation and the gratuitous use
of filescope variables, and '//' comments on very long lines suggests that
yours is a joke post (but not a very good one). Be that as it may,
is a terrible thing to suggest. Not even the most clueless poster deserves
to be treated that way.
What? He asked for a program and I gave him one. Not a very good one, but it
would work. No-one else even bothered to write one.
 
M

Mike Wahler

MikeyD said:
What? He asked for a program and I gave him one. Not a very good one, but it
would work. No-one else even bothered to write one.

Really? My example can beat up your example. :)

-Mike
 
M

MikeyD

What? He asked for a program and I gave him one. Not a very good one,
but
it

Really? My example can beat up your example. :)

-Mike
Sorry, yes, you're right as a general program. But if he just wants to count
between those two particular directives then mine'll be easier for him to
use. I'll just fix it for commandline input, but that was chapter...actually
it wasn't in C for dummies at all.
Maybe this should be used as an example of how not to code whilst still
getting a working program.
#include <stdio.h>
char filepath[100];
char tstr[10];
int lines;
FILE* cfile
int main(int whatever, char**notaclue){
lines=0
if(whatever==1)goto meaninglesslabel;
printf("I didn't understand the arguments you gave me, so what's the file
then?\n");
gets(filepath);
goto evenworse;
meaninglesslabel: filepath=notaclue[1];//or should this be 0? I never really
//worked out how the ags are arranged
evenworse:
cfile=fopen(filepath, "r");
fseek(cfile,SEEK_SET);//not sure if this is correctly formulated
for(;strcmp(tstr,"#ifdef win32")!=0;fgets(cfile,tstr));//value for strcmp
//may be wrong, fgets args may also be wrong
for(;strcmp(tstr,"#endif")!=0;fgets(cfile,tstr)) lines++;
printf("There were %d lines between the pre-processor commands\n",lines);
//is this how you want it returned?
return lines; //or return 0;
}
 
M

MikeyD

Martin Ambuhl said:
Please stop this. No one deserves to be treated to this antisocial "advise."
It's just there as a backup now that I've fixed the commandline bit. There
are flaws with fgets() as well (the site mentions its failure to delete \n
at the end, I'm sure I've read of others) Obviously it's best to use your
own getstring() function but I can't rely on him having my personal function
library. For a utility program like this, gets() is perfectly suitable.
And on what grounds do you claim it's antisocial??
 
I

Irrwahn Grausewitz

MikeyD said:
It's just there as a backup now that I've fixed the commandline bit. There
are flaws with fgets() as well (the site mentions its failure to delete \n
at the end, I'm sure I've read of others) Obviously it's best to use your
own getstring() function but I can't rely on him having my personal function
library. For a utility program like this, gets() is perfectly suitable.
And on what grounds do you claim it's antisocial??
gets() is suitable for absolutely nothing, except breaking your code.
And AFICS that's why Martin claimed it antisocial to suggest to use it.

Irrwahn
 
M

Martin Ambuhl

MikeyD said:
"advise."

It's just there as a backup now that I've fixed the commandline bit. There
are flaws with fgets() as well (the site mentions its failure to delete \n
at the end, I'm sure I've read of others)

There may be flaws in fgets(), but not deleting '\n' is not one of them.
Dan Pop will probably provide a list of what's *really* wrong (on his vies)
with fgets(). If you think not deleting '\n' is a flaw, then you haven't
been programming long enough.

There is no such thing as using gets "as a backup." Using an inherently
dangerous function that ought never be used is not "a backup."
> Obviously it's best to use your
own getstring() function

That's not obvious. There are situation in which having your own
getstring() function has attractions, though.
but I can't rely on him having my personal function
library.

What crap. If you want your own getstring() function just write the damn
thing and stick it in and you will be 100% sure of having it.
For a utility program like this, gets() is perfectly suitable.
Bullshit.

And on what grounds do you claim it's antisocial??

You are suggesting the use of inherently unsafe functions for which use
there is no excuse. Why not just hand out guns to children?
 
M

MikeyD

Fine then.
#include <stdio.h>
#include <stdlib.h>
char filepath[100];
char tstr[10];
int lines;
FILE* cfile
int main(int whatever, char**notaclue){
lines=0
if(whatever==1)goto meaninglesslabel;
printf("I didn't understand the arguments you gave me, so what's the file
then?\n");
for(int i=0;i<100;i++){filepath=getchar();
if(filepath=='\n'){
filepath='\0';
break;}
if(i==99){
printf("You entered too long a filename");
exit(1);
}}
goto evenworse;
meaninglesslabel: strcpy(filepath,notaclue[1]);//or should this be 0? I
never really
//worked out how the ags are arranged
evenworse:
cfile=fopen(filepath, "r");
fseek(cfile,SEEK_SET);//not sure if this is correctly formulated
for(;strcmp(tstr,"#ifdef win32")!=0;fgets(cfile,tstr));//value for strcmp
//may be wrong, fgets args may also be wrong
for(;strcmp(tstr,"#endif")!=0;fgets(cfile,tstr)) lines++;
printf("There were %d lines between the pre-processor commands\n",lines);
//is this how you want it returned?
return lines; //or return 0;
}
Happy now?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top