Go Back   Velocity Reviews > Newsgroups > C Programming
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

C Programming - preprocessor arithmetic

 
Thread Tools Search this Thread
Old 10-29-2009, 03:11 AM   #21
Default Re: preprocessor arithmetic


On Oct 28, 10:59*pm, Andrey Vul <andrey....@gmail.com> wrote:

>
> Here's my code so far:
>
> Note: there a script that generates for n=5,8,11,etc.
> That output file is specified via -Di=...
> #ifdef IDEF
> #define I #ifndef
> #define D #define
> #define E #endif
> #endif
> #ifdef i
> #include #i
> #endif
> #define _C(x,y) x##y
> #define C(x,y) _C(x,y)
> #define F(x) C(F,x)
> #ifndef R
> I F(0)
> I F(1)
> I F(2)
> D F(0) 1
> D F(1) 1
> D F(2) 1
> E
> E
> E
> I F(n_2)
> D F(n_2) (F(n_3)+F(n_4))
> E
> I F(n_1)
> D F(n_1) (F(n_2)+F(n_3))
> E
> E
> I F(n)
> D F(n) (F(n_1)+F(n_2))
> E
> #endif
> #if (n>=1)
> F(n)
> #define R
> /* How do I decrement n here */
> #include __FILE__
> #endif


n_[1-3] are defined via shell in this form:
export n; cpp foo.c -Dn=$n -Dn_1=$(($n-1)) -Dn_2=$(($n-2)) -Dn_3=$
(($n-3))
If that helps.


Andrey Vul
  Reply With Quote
Old 10-29-2009, 03:29 AM   #22
Andrey Vul
 
Posts: n/a
Default Re: preprocessor arithmetic
On Oct 29, 12:19*am, Thad Smith <ThadSm...@acm.org> wrote:
> Andrey Vul wrote:
> > On Oct 28, 10:42 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
> >> Andrey Vul wrote:

>
> >>> It looks like cpp uses a list to store define chains:
> >>> #define a b
> >>> #define b c
> >>> => a => (b is expandable ? c : b)
> >> * * *No. *See 6.10.3.4.

>
> >>> I'm asking if there's a way to force cpp to _not_ linklist #define
> >>> chains.
> >> * * *Yes: Just use it as it stands; there are no chains or lists
> >> of definitions. *See 6.10.3.4.

>
> > Multi-pass somehow registers with me as linked lists. My bad.
> > But 6.10.3.4 is what I'm trying to subvert.

>
> Perhaps you should implement your own preprocessor or other code
> generator to do what you want.

Somehow, when I want to mix code and macros, the simplest solution
becomes to make a simple, 275-line preprocessor like this:
/* Simple macro processor.
* 2009-10-26-7 Andrey Vul <>
*
* Usage:
* smp specfile infile
*
* Limitations: no recursion support
* all macros must be unary
* one macro definition per spec file
*
* Spec file format:
* initializer-for-invocation-argument-list terminator
* #include "baseformat
* printf-syntax-for-output-filename
* #include < ... > in-header
* delimiter
* [no]incguard [...]
* macro-definition
* ...
* /*
*/

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

#ifdef _MSC_VER
# define LINE_MAX 1024
# pragma warning (disable: 4996)
#include <io.h>
#else
#include <unistd.h>
#endif

#ifndef _MSC_VER
# include <libgen.h>
# include <sys/types.h>
# include <sys/stat.h>
#else
# include "w32-dirname.c"
#endif

char **tokens;
char **includeonce;
char *usemacro;
char *usemacro_term;
char *find_include_h;
char *outfmt;
char *incguard[2];
static const char *find_incguard[2] = { "noincguard", "incguard" };
int dodebug;

#define debug(x) x

long flen(FILE *fp) {
long cur, end;
cur = ftell(fp);
fseek(fp, 0, SEEK_END);
end = ftell(fp);
fseek(fp, cur, SEEK_SET);
return end;
}

char *p_strcat(char *dest, const char *src) {
strcat(dest, src);
return strchr(dest, '\0');
}

char *find_outfile_name(const char *inpath, FILE *in) {
char outname[65536];
char line[LINE_MAX];
char *component = NULL;
char *ip = strdup(inpath);
//memset(line, 0, LINE_MAX);
rewind(in);
while (!feof(in)){
fgets(line, LINE_MAX, in);
if (strncmp(line, find_include_h, strlen(find_include_h)) == 0) {
strtok(line, ".");
component = strtok(NULL, ".");
break;
}
}
if (component == NULL)
return NULL;
sprintf(outname, outfmt, dirname(ip), component);
free(ip);
return strdup(outname);
}

/* return envp-style list of types to define */
char **usingarray_types(FILE *in) {
char **out = NULL;
unsigned n = 0;
char line[LINE_MAX];
char *tok;
rewind(in);
while (fgets(line, LINE_MAX, in) != NULL) {
if (strncmp(line, usemacro, strlen(usemacro)) == 0) {
strtok(line, " ");
while ((tok = strtok(NULL, " ")) != NULL) {
out = realloc(out, sizeof(char *) * (n + 1));
if (strncmp(tok, usemacro_term, strlen(usemacro_term)) != 0)
out[n] = strdup(tok);
else {
out[n] = NULL;
break;
}
n++;

}
break;
}
}
return out;
}


void remove_newline(char *s) {
char *s_n = strrchr(s, '\n');
if (s_n)
*(s_n) = '\0';
}

/* Get the size of the largest string in the null-terminated array */
size_t strza_maxlen(const char **strza) {
size_t m = 0, l;
const char **__za = strza;
while (*__za) {
l = strlen(*__za);
if (m > l)
m = l;
__za++;
}
return m;
}

const char *Z_(const char *s) {
static const char Z[] = "";
if (s != NULL)
return s;
else
return (const char *)Z;
}

void parse_spec(const char *specfile) {
FILE *in;
char line[LINE_MAX];
int fd;
char delim[2];
unsigned cnt;
char *tok;
char *filebuf;
long fl;
int rd;
in = fopen(specfile, "r");
fgets(line, LINE_MAX, in);
cnt = 0;
/* initialize usemacro, usemacro_term */
usemacro = strdup(strtok(line, " "));
usemacro_term = strdup(strtok(NULL, " "));
remove_newline(usemacro_term);
/* initialize find_include_h */
fgets(line, LINE_MAX, in);
find_include_h = strdup(line);
remove_newline(find_include_h);
/* initialize outfmt */
fgets(line, LINE_MAX, in);
outfmt = strdup(line);
remove_newline(outfmt);
/* populate includeonce */
fgets(line, LINE_MAX, in);
remove_newline(line);
tok = strtok(line, " ");
includeonce = NULL;
cnt = 0;
if (tok != NULL) {
includeonce = malloc(sizeof(char *));
includeonce[cnt++] = strdup(line);
while ((tok = strtok(NULL, " ")) != NULL) {
includeonce = realloc(includeonce, sizeof(char *) * (cnt + 1));
includeonce[cnt++] = strdup(tok);
}
}
includeonce = realloc(includeonce, sizeof(char *) * (cnt + 1));
includeonce[cnt] = NULL;
/* get delimiter */
fgets(line, LINE_MAX, in);
delim[0] = line[0];
delim[1] = '\0';
/* get include guard */
fgets(line, LINE_MAX, in);
remove_newline(line);
if (strncmp(line, find_incguard[0], strlen(find_incguard[0])) == 0) {
incguard[0] = NULL;
incguard[1] = NULL;
} else if (strncmp(line, find_incguard[1], strlen(find_incguard[1]))
== 0) {
incguard[0] = strdup(strtok(strchr(line, ' '), delim));
incguard[1] = strdup(strtok(NULL, delim));
} else {
printf("fatal: include guard options not defined\n");
abort();
}
debug(printf("debug: incg[0]=%s incg[1]=%s\n", incguard[0], incguard
[1]));
/* tokenize rest of file by delimiter */
fl = flen(in);
filebuf = malloc(fl + 1);
rd = fread(filebuf, 1, fl, in);
if (rd >= 0)
filebuf[rd] = '\0';
tok = strtok(filebuf, delim);
tokens = NULL;
cnt = 0;
if (tok != NULL) {
tokens = malloc(sizeof(char *));
tokens[cnt++] = strdup(tok);
while ((tok = strtok(NULL, delim)) != NULL) {
tokens = realloc(tokens, sizeof(char *) * (cnt + 1));
tokens[cnt++] = strdup(tok);
}
}
tokens = realloc(tokens, sizeof(char *) * (cnt + 1));
tokens[cnt] = NULL;
}

int main(int argc, char **argv) {
char *outname;
char **ctokp;
char **type, **ctypep;
char **cincp;
char *incg, *incgp;
size_t type_maxlen;
FILE *inf, *outf;
if (argc != 3) {
printf("error: incorrect number of args\n"
"usage: %s specfile infile\n", argv[0]);
return 1;
}
parse_spec(argv[1]);
inf = fopen(argv[2], "r");
outname = find_outfile_name(argv[2], inf);
type = usingarray_types(inf);
printf("%s\n", outname);
outf = fopen(outname, "w");
/* includeonce */
cincp = includeonce;
while (*cincp) {
fputs("#include ", outf);
fputs(*cincp, outf);
fputc('\n', outf);
cincp++;
}
ctypep = type;
type_maxlen = strza_maxlen(type);
if (incguard[0] != NULL) {
incg = malloc(strlen(incguard[0]) + strlen(Z_(incguard[1])) +
type_maxlen + 1);
incg[0] = '\0';
incgp = p_strcat(incg, incguard[0]);
} else {
incg = NULL;
incgp = NULL;
}
while (*ctypep) {
if (incg != NULL) {
*incgp = '\0';
p_strcat(incgp, *ctypep);
p_strcat(incgp, Z_(incguard[1]));
debug(printf("debug: incg=%s\n", incg));
fprintf(outf, "#ifndef %s\n"
"#define %s\n",
incg, incg);
}
ctokp = tokens;
while (*ctokp) {
fputs(*ctokp, outf);
fputs(*ctypep, outf);
ctokp++;
}
fputs("*/\n", outf);
if (incg != NULL)
fprintf(outf, "#endif /* %s */\n", incg);
ctypep++;
}
if (incg)
free(incg);
fclose(inf);
fclose(outf);
return 0;
}

that parses this:
/*usingarray */
#include "array.
%s/array.%s.h
<stdlib.h> <string.h> <errno.h>
@
incguard ARRAY_@_H

typedef struct {
@ *p;
size_t size;
} array$@;

array$@ *array$@$new(size_t size) {
array$@ *a = malloc(sizeof(array$@));
if (a == NULL) {
errno = ENOMEM;
return NULL;
}
a->size = size;
a->p = (@ *)malloc(sizeof(@) * a->size);
if (a->p == NULL) {
errno = ENOMEM;
free(a);
return NULL;
}
return a;
}

void array$@$delete(array$@ * restrict p) {
if (p == NULL) {
errno = EINVAL;
return;
}
if (p->p != NULL)
free(p->p);
free(p);
}

@ *array$@$reference(array$@ * restrict p, size_t i) {
if (p == NULL) {
errno = EINVAL;
return NULL;
}
if (i >= p->size) {
errno = EINVAL;
return NULL;
}
return ((p->p) + i);
}

int array$@$set_range(array$@ * restrict p, @ * restrict a,
size_t from, size_t len)
{
if (p == NULL || a == NULL) {
errno = EINVAL;
return 1;
}
if (from + len > p->size) {
errno = EINVAL;
return 2;
}
memcpy(array$@$reference(p, from), a, len * sizeof(@));
return 0;
}

#define array$@$at(p, i) (*array$@$reference(p, i))

/*

The /* at the end is a bugfix since the preprocessor adds the
expansion after every token. It works well, so who cares?


Andrey Vul
  Reply With Quote
Old 10-29-2009, 03:41 AM   #23
Seebs
 
Posts: n/a
Default Re: preprocessor arithmetic
On 2009-10-29, Andrey Vul <> wrote:
> Use the defined decrement macros in a cpp-fibonacci to decrement the
> previous macros.


Don't.

> #define I #ifndef
> #define D #define
> #define E #endif


Don't do this.

> /* How do I decrement n here */


You don't, really.

This is not a thing the C preprocessor is intended to accommodate. It
was discussed at one of the Toronto meetings, and the conclusion was that,
basically, implementors didn't want to spend time fussing with cpp.

If you want to write more flexible macros, use something other than cpp to
generate C code.

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!


Seebs
  Reply With Quote
Old 10-29-2009, 04:06 AM   #24
Chris M. Thomasson
 
Posts: n/a
Default Re: preprocessor arithmetic
> "Andrey Vul" <> wrote in message
> news:85ae4fa8-2a08-4c42-80aa-...

[...]

Think of what I'm trying to do as factorial via preprocessor (i.e. the
> expansion of f(5) would be (5*(4*(3*(2*(1))))) ,but how do you tail
> decrement and recurse properly?
> I use #ifndef RECURSION ... #endif to shield the non-recursive part
> and #if (TOKEN > 1) TOKEN * (DEC(TOKEN)) #endif
> but DEC has no
> DEC1 0
> DEC2 1

__________________________________________________ ________________
#include <stdio.h>


#define QUOTEX(t)#t
#define QUOTE(t)QUOTEX(t)


#define CONCATX(t1, t2)t1##t2
#define CONCAT(t1, t2)CONCATX(t1, t2)


#define X_1(n) (n)
#define X_2(n) (n * X_1(1))
#define X_3(n) (n * X_2(2))
#define X_4(n) (n * X_3(3))
#define X_5(n) (n * X_4(4))
#define X_6(n) (n * X_5(5))
#define X(n) CONCAT(X_, n)(n)


int
main(void)
{
printf("factorial 6 == " QUOTE(X(6)) " == %u\n", X(6));
printf("factorial 5 == " QUOTE(X(5)) " == %u\n", X(5));
printf("factorial 4 == " QUOTE(X(4)) " == %u\n", X(4));
printf("factorial 3 == " QUOTE(X(3)) " == %u\n", X(3));
printf("factorial 2 == " QUOTE(X(2)) " == %u\n", X(2));
printf("factorial 1 == " QUOTE(X(1)) " == %u\n", X(1));

return 0;
}
__________________________________________________ ________________




automatic pre-processor generation of factorials. Is that good enough?

;^o



Chris M. Thomasson
  Reply With Quote
Old 10-29-2009, 04:19 AM   #25
Thad Smith
 
Posts: n/a
Default Re: preprocessor arithmetic
Andrey Vul wrote:
> On Oct 28, 10:42 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>> Andrey Vul wrote:
>>

>
>>> It looks like cpp uses a list to store define chains:
>>> #define a b
>>> #define b c
>>> => a => (b is expandable ? c : b)

>> No. See 6.10.3.4.
>>
>>> I'm asking if there's a way to force cpp to _not_ linklist #define
>>> chains.

>> Yes: Just use it as it stands; there are no chains or lists
>> of definitions. See 6.10.3.4.

>
> Multi-pass somehow registers with me as linked lists. My bad.
> But 6.10.3.4 is what I'm trying to subvert.


Perhaps you should implement your own preprocessor or other code
generator to do what you want.

--
Thad


Thad Smith
  Reply With Quote
Old 10-29-2009, 10:07 AM   #26
Nick Keighley
 
Posts: n/a
Default Re: preprocessor arithmetic
On 29 Oct, 02:42, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
> Andrey Vul wrote:


<snip>

> *I repeat my suggestion
> that you refrain from attempting fancy tricks with the
> preprocessor until you understand the tool you are trying
> to use. *At the moment, your mental model of the preprocessor
> appears to approximate reality somewhat inexactly.


ah, but perhaps he's trying to improve his mental model. Perhaps
reading the standard would be better than guessing though.

<snip>


Nick Keighley
  Reply With Quote
Old 10-29-2009, 10:09 AM   #27
Nick Keighley
 
Posts: n/a
Default Re: preprocessor arithmetic
On 29 Oct, 02:18, Andrey Vul <andrey....@gmail.com> wrote:

> There's an easy way to do it, and an interesting way to do it. Guess
> what I chose


swimming in channel in a suit of armour would probably be interesting
too


Nick Keighley
  Reply With Quote
Old 10-29-2009, 12:05 PM   #28
Eric Sosman
 
Posts: n/a
Default Re: preprocessor arithmetic
Andrey Vul wrote:
>
> But 6.10.3.4 is what I'm trying to subvert.


Then don't use C.

--
Eric Sosman
lid


Eric Sosman
  Reply With Quote
Old 10-29-2009, 12:09 PM   #29
Eric Sosman
 
Posts: n/a
Default Re: preprocessor arithmetic
Nick Keighley wrote:
> On 29 Oct, 02:42, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>> Andrey Vul wrote:

>
> <snip>
>
>> I repeat my suggestion
>> that you refrain from attempting fancy tricks with the
>> preprocessor until you understand the tool you are trying
>> to use. At the moment, your mental model of the preprocessor
>> appears to approximate reality somewhat inexactly.

>
> ah, but perhaps he's trying to improve his mental model. Perhaps
> reading the standard would be better than guessing though.


There is nothing objectionable about trying to improve
one's mental model; quite the opposite, it's praiseworthy.
But my suggestion still stands: He shouldn't be trying the
sort of tricks he's doing until *after* the model improves.

Calvin: "Mom, do we have any chain saws in the house?"

His Mother: "No. Why?"

Calvin: "Rats! How am I going to learn to juggle?"

--
Eric Sosman
lid


Eric Sosman
  Reply With Quote
Old 10-29-2009, 12:16 PM   #30
Eric Sosman
 
Posts: n/a
Default Re: preprocessor arithmetic
Andrey Vul wrote:
> [...]
> Think of what I'm trying to do as factorial via preprocessor (i.e. the
> expansion of f(5) would be (5*(4*(3*(2*(1))))) ,but how do you tail
> decrement and recurse properly?


You don't. Macros do not expand recursively, period.
Macros do not iterate, period. End of story. Wrong tool
for the job. Brushing your teeth with a bulldozer. Don't.

--
Eric Sosman
lid


Eric Sosman
  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




SEO by vBSEO 3.3.2 ©2009, Crawlability, Inc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46