![]() |
|
|
|
#21 |
|
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 |
|
|
|
|
#22 |
|
Posts: n/a
|
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 |
|
|
|
#23 |
|
Posts: n/a
|
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 |
|
|
|
#24 |
|
Posts: n/a
|
> "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 |
|
|
|
#25 |
|
Posts: n/a
|
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 |
|
|
|
#26 |
|
Posts: n/a
|
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 |
|
|
|
#27 |
|
Posts: n/a
|
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 |
|
|
|
#28 |
|
Posts: n/a
|
|
|
|
|
#29 |
|
Posts: n/a
|
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 |
|
|
|
#30 |
|
Posts: n/a
|
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 |
|