How to use customize assert marco - c

tmp2.c
/*
gcc -Wall -Werror -g assert.c tmp2.c && ./a.out
*/
#include "tmp2.h"
#include <assert.h>
int main(void)
{
// assert(1 == 2);
Assert(1 == 2);
return 0;
}
tmp2.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <math.h>
#include<stdint.h>
#include<stdalign.h>
#include<stdbool.h>
/*
* BoolIsValid
* True iff bool is valid.
*/
#define BoolIsValid(boolean) ((boolean) == false || (boolean) == true)
/*
* PointerIsValid
* True iff pointer is valid.
*/
#define PointerIsValid(pointer) ((const void*)(pointer) != NULL)
extern void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber);
/*
* USE_ASSERT_CHECKING, if defined, turns on all the assertions.
* - plai 9/5/90
*
* It should _NOT_ be defined in releases or in benchmark copies
*/
/*
* Assert() can be used in both frontend and backend code. In frontend code it
* just calls the standard assert, if it's available. If use of assertions is
* not configured, it does nothing.
*/
#define USE_ASSERT_CHECKING 0
#ifndef USE_ASSERT_CHECKING
#define Assert(condition) ((void)true)
#define AssertMarcod(condition) ((void)true)
#elif defined(FRONTEND)
#include<assert.h>
#define Assert(p) assert(p)
#define AssertMarco(p) ((void) assert(p))
#else
/*
* Assert
* Generates a fatal exception if the given condition is false.
*/
#define Assert(condition) \
do { \
if (!(condition)) \
ExceptionalCondition(#condition,__FILE__,__LINE__); \
} while (0)
/*
* AssertMacro is the same as Assert but it's suitable for use in
* expression-like macros, for example:
*
* #define foo(x) (AssertMacro(x != 0), bar(x))
*/
#define AssertMacro(condition) \
((void) ((condition) || \
(ExceptionalCondition(#condition,__FILE__,__LINE__),0)))
#endif
assert.c
#include "tmp2.h"
#include <unistd.h>
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
/*
* ExceptionalCondition - Handles the failure of an Assert()
*
* We intentionally do not go through elog() here, on the grounds of
* wanting to minimize the amount of infrastructure that has to be
* working to report an assertion failure.
*/
void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber)
{
/* Report the failure on stderr (or local equivalent) */
if (!PointerIsValid(conditionName)
|| !PointerIsValid(fileName))
fprintf(stderr,"TRAP: ExceptionalCondition: bad arguments in PID %d\n",
(int) getpid());
else
fprintf(stderr,"TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n",
conditionName, fileName, lineNumber, (int) getpid());
/* Usually this shouldn't be needed, but make sure the msg went out */
fflush(stderr);
// /* If we have support for it, dump a simple backtrace */
// #ifdef HAVE_BACKTRACE_SYMBOLS
// {
// void *buf[100];
// int nframes;
// nframes = backtrace(buf, lengthof(buf));
// backtrace_symbols_fd(buf, nframes, fileno(stderr));
// }
// #endif
/*
* If configured to do so, sleep indefinitely to allow user to attach a
* debugger. It would be nice to use pg_usleep() here, but that can sleep
* at most 2G usec or ~33 minutes, which seems too short.
*/
#ifdef SLEEP_ON_ASSERT
sleep(1000000);
#endif
abort();
}
In this context, I'm trying a way to use the AssertMacro; that is, find a way to invoke assert.c ExceptionalCondition function. Assume FRONTEND is not defined. USE_ASSERT_CHECKING can be 1 or 0.
update: to use ExceptionalCondition function I need to declare it on tmp2.h via
extern void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber);
I also need to define USE_ASSERT_CHECKING in tmp2.h or before tmp2.h.
If I don't define USE_ASSERT_CHECKING seems all the assert will be true always?

Related

How to define an array of structs at compile time composed of static (private) structs from separate modules?

This question is something of a trick C question or a trick clang/gcc question. I'm not sure which.
I phrased it like I did because the final array is in main.c, but the structs that are in the array are defined in C modules.
The end goal of what I am trying to do is to be able to define structs in seperate C modules and then have those structs be available in a contiguous array right from program start. I do not want to use any dynamic code to declare the array and put in the elements.
I would like it all done at compile or link time -- not at run time.
I'm looking to end up with a monolithic blob of memory that gets setup right from program start.
For the sake of the Stack Overflow question, I thought it would make sense if I imagined these as "drivers" (like in the Linux kernel) Going with that...
Each module is a driver. Because the team is complex, I do not know how many drivers there will ultimately be.
Requirements:
Loaded into contiguous memory (an array)
Loaded into memory at program start
installed by the compiler/linker, not dynamic code
a driver exists because source code exists for it (no dynamic code to load them up)
Avoid cluttering up the code
Here is a contrived example:
// myapp.h
//////////////////////////
struct state
{
int16_t data[10];
};
struct driver
{
char name[255];
int16_t (*on_do_stuff) (struct state *state);
/* other stuff snipped out */
};
// drivera.c
//////////////////////////
#include "myapp.h"
static int16_t _on_do_stuff(struct state *state)
{
/* do stuff */
}
static const struct driver _driver = {
.name = "drivera",
.on_do_stuff = _on_do_stuff
};
// driverb.c
//////////////////////////
#include "myapp.h"
static int16_t _on_do_stuff(struct state *state)
{
/* do stuff */
}
static const struct driver _driver = {
.name = "driverb",
.on_do_stuff = _on_do_stuff
};
// driverc.c
//////////////////////////
#include "myapp.h"
static int16_t _on_do_stuff(struct state *state)
{
/* do stuff */
}
static const struct driver _driver = {
.name = "driverc",
.on_do_stuff = _on_do_stuff
};
// main.c
//////////////////////////
#include <stdio.h>
static struct driver the_drivers[] = {
{drivera somehow},
{driverb somehow},
{driverc somehow},
{0}
};
int main(void)
{
struct state state;
struct driver *current = the_drivers;
while (current != 0)
{
printf("we are up to %s\n", current->name);
current->on_do_stuff(&state);
current += sizeof(struct driver);
}
return 0;
}
This doesn't work exactly.
Ideas:
On the module-level structs, I could remove the static const keywords, but I'm not sure how to get them into the array at compile time
I could move all of the module-level structs to main.c, but then I would need to remove the static keyword from all of the on_do_stuff functions, and thereby clutter up the namespace.
In the Linux kernel, they somehow define kernel modules in separate files and then through linker magic, they are able to be loaded into monolithics
Use a dedicated ELF section to "collect" the data structures.
For example, define your data structure in info.h as
#ifndef INFO_H
#define INFO_H
#ifndef INFO_ALIGNMENT
#if defined(__LP64__)
#define INFO_ALIGNMENT 16
#else
#define INFO_ALIGNMENT 8
#endif
#endif
struct info {
long key;
long val;
} __attribute__((__aligned__(INFO_ALIGNMENT)));
#define INFO_NAME(counter) INFO_CAT(info_, counter)
#define INFO_CAT(a, b) INFO_DUMMY() a ## b
#define INFO_DUMMY()
#define DEFINE_INFO(data...) \
static struct info INFO_NAME(__COUNTER__) \
__attribute__((__used__, __section__("info"))) \
= { data }
#endif /* INFO_H */
The INFO_ALIGNMENT macro is the alignment used by the linker to place each symbol, separately, to the info section. It is important that the C compiler agrees, as otherwise the section contents cannot be treated as an array. (You'll obtain an incorrect number of structures, and only the first one (plus every N'th) will be correct, the rest of the structures garbled. Essentially, the C compiler and the linker disagreed on the size of each structure in the section "array".)
Note that you can add preprocessor macros to fine-tune the INFO_ALIGNMENT for each of the architectures you use, but you can also override it for example in your Makefile, at compile time. (For GCC, supply -DINFO_ALIGNMENT=32 for example.)
The used attribute ensures that the definition is emitted in the object file, even though it is not referenced otherwise in the same data file. The section("info") attribute puts the data into a special info section in the object file. The section name (info) is up to you.
Those are the critical parts, otherwise it is completely up to you how you define the macro, or whether you define it at all. Using the macro is easy, because one does not need to worry about using unique variable name for the structure. Also, if at least one member is specified, all others will be initialized to zero.
In the source files, you define the data objects as e.g.
#include "info.h"
/* Suggested, easy way */
DEFINE_INFO(.key = 5, .val = 42);
/* Alternative way, without relying on any macros */
static struct info foo __attribute__((__used__, __section__("info"))) = {
.key = 2,
.val = 1
};
The linker provides symbols __start_info and __stop_info, to obtain the structures in the info section. In your main.c, use for example
#include "info.h"
extern struct info __start_info[];
extern struct info __stop_info[];
#define NUM_INFO ((size_t)(__stop_info - __start_info))
#define INFO(i) ((__start_info) + (i))
so you can enumerate all info structures. For example,
int main(void)
{
size_t i;
printf("There are %zu info structures:\n", NUM_INFO);
for (i = 0; i < NUM_INFO; i++)
printf(" %zu. key=%ld, val=%ld\n", i,
__start_info[i].key, INFO(i)->val);
return EXIT_SUCCESS;
}
For illustration, I used both the __start_info[] array access (you can obviously #define SOMENAME __start_info if you want, just make sure you do not use SOMENAME elsewhere in main.c, so you can use SOMENAME[] as the array instead), as well as the INFO() macro.
Let's look at a practical example, an RPN calculator.
We use section ops to define the operations, using facilities defined in ops.h:
#ifndef OPS_H
#define OPS_H
#include <stdlib.h>
#include <errno.h>
#ifndef ALIGN_SECTION
#if defined(__LP64__) || defined(_LP64)
#define ALIGN_SECTION __attribute__((__aligned__(16)))
#elif defined(__ILP32__) || defined(_ILP32)
#define ALIGN_SECTION __attribute__((__aligned__(8)))
#else
#define ALIGN_SECTION
#endif
#endif
typedef struct {
size_t maxsize; /* Number of values allocated for */
size_t size; /* Number of values in stack */
double *value; /* Values, oldest first */
} stack;
#define STACK_INITIALIZER { 0, 0, NULL }
struct op {
const char *name; /* Operation name */
const char *desc; /* Description */
int (*func)(stack *); /* Implementation */
} ALIGN_SECTION;
#define OPS_NAME(counter) OPS_CAT(op_, counter, _struct)
#define OPS_CAT(a, b, c) OPS_DUMMY() a ## b ## c
#define OPS_DUMMY()
#define DEFINE_OP(name, func, desc) \
static struct op OPS_NAME(__COUNTER__) \
__attribute__((__used__, __section__("ops"))) = { name, desc, func }
static inline int stack_has(stack *st, const size_t num)
{
if (!st)
return EINVAL;
if (st->size < num)
return ENOENT;
return 0;
}
static inline int stack_pop(stack *st, double *to)
{
if (!st)
return EINVAL;
if (st->size < 1)
return ENOENT;
st->size--;
if (to)
*to = st->value[st->size];
return 0;
}
static inline int stack_push(stack *st, double val)
{
if (!st)
return EINVAL;
if (st->size >= st->maxsize) {
const size_t maxsize = (st->size | 127) + 129;
double *value;
value = realloc(st->value, maxsize * sizeof (double));
if (!value)
return ENOMEM;
st->maxsize = maxsize;
st->value = value;
}
st->value[st->size++] = val;
return 0;
}
#endif /* OPS_H */
The basic set of operations is defined in ops-basic.c:
#include "ops.h"
static int do_neg(stack *st)
{
double temp;
int retval;
retval = stack_pop(st, &temp);
if (retval)
return retval;
return stack_push(st, -temp);
}
static int do_add(stack *st)
{
int retval;
retval = stack_has(st, 2);
if (retval)
return retval;
st->value[st->size - 2] = st->value[st->size - 1] + st->value[st->size - 2];
st->size--;
return 0;
}
static int do_sub(stack *st)
{
int retval;
retval = stack_has(st, 2);
if (retval)
return retval;
st->value[st->size - 2] = st->value[st->size - 1] - st->value[st->size - 2];
st->size--;
return 0;
}
static int do_mul(stack *st)
{
int retval;
retval = stack_has(st, 2);
if (retval)
return retval;
st->value[st->size - 2] = st->value[st->size - 1] * st->value[st->size - 2];
st->size--;
return 0;
}
static int do_div(stack *st)
{
int retval;
retval = stack_has(st, 2);
if (retval)
return retval;
st->value[st->size - 2] = st->value[st->size - 1] / st->value[st->size - 2];
st->size--;
return 0;
}
DEFINE_OP("neg", do_neg, "Negate current operand");
DEFINE_OP("add", do_add, "Add current and previous operands");
DEFINE_OP("sub", do_sub, "Subtract previous operand from current one");
DEFINE_OP("mul", do_mul, "Multiply previous and current operands");
DEFINE_OP("div", do_div, "Divide current operand by the previous operand");
The calculator expects each value and operand to be a separate command-line argument for simplicity. Our main.c contains operation lookup, basic usage, value parsing, and printing the result (or error):
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "ops.h"
extern struct op __start_ops[];
extern struct op __stop_ops[];
#define NUM_OPS ((size_t)(__stop_ops - __start_ops))
static int do_op(stack *st, const char *opname)
{
struct op *curr_op;
if (!st || !opname)
return EINVAL;
for (curr_op = __start_ops; curr_op < __stop_ops; curr_op++)
if (!strcmp(opname, curr_op->name))
break;
if (curr_op >= __stop_ops)
return ENOTSUP;
return curr_op->func(st);
}
static int usage(const char *argv0)
{
struct op *curr_op;
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv0);
fprintf(stderr, " %s RPN-EXPRESSION\n", argv0);
fprintf(stderr, "\n");
fprintf(stderr, "Where RPN-EXPRESSION is an expression using reverse\n");
fprintf(stderr, "Polish notation, and each argument is a separate value\n");
fprintf(stderr, "or operator. The following operators are supported:\n");
for (curr_op = __start_ops; curr_op < __stop_ops; curr_op++)
fprintf(stderr, "\t%-14s %s\n", curr_op->name, curr_op->desc);
fprintf(stderr, "\n");
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
stack all = STACK_INITIALIZER;
double val;
size_t i;
int arg, err;
char dummy;
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
return usage(argv[0]);
for (arg = 1; arg < argc; arg++)
if (sscanf(argv[arg], " %lf %c", &val, &dummy) == 1) {
err = stack_push(&all, val);
if (err) {
fprintf(stderr, "Cannot push %s to stack: %s.\n", argv[arg], strerror(err));
return EXIT_FAILURE;
}
} else {
err = do_op(&all, argv[arg]);
if (err == ENOTSUP) {
fprintf(stderr, "%s: Operation not supported.\n", argv[arg]);
return EXIT_FAILURE;
} else
if (err) {
fprintf(stderr, "%s: Cannot perform operation: %s.\n", argv[arg], strerror(err));
return EXIT_FAILURE;
}
}
if (all.size < 1) {
fprintf(stderr, "No result.\n");
return EXIT_FAILURE;
} else
if (all.size > 1) {
fprintf(stderr, "Multiple results:\n");
for (i = 0; i < all.size; i++)
fprintf(stderr, " %.9f\n", all.value[i]);
return EXIT_FAILURE;
}
printf("%.9f\n", all.value[0]);
return EXIT_SUCCESS;
}
Note that if there were many operations, constructing a hash table to speed up the operation lookup would make a lot of sense.
Finally, we need a Makefile to tie it all together:
CC := gcc
CFLAGS := -Wall -O2 -std=c99
LDFLAGS := -lm
OPS := $(wildcard ops-*.c)
OPSOBJS := $(OPS:%.c=%.o)
PROGS := rpncalc
.PHONY: all clean
all: clean $(PROGS)
clean:
rm -f *.o $(PROGS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
rpncalc: main.o $(OPSOBJS)
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Because this forum does not preserve Tabs, and make requires them for indentation, you probably need to fix the indentation after copy-pasting the above. I use sed -e 's|^ *|\t|' -i Makefile
If you compile (make clean all) and run (./rpncalc) the above, you'll see the usage information:
Usage: ./rpncalc [ -h | --help ]
./rpncalc RPN-EXPRESSION
Where RPN-EXPRESSION is an expression using reverse
Polish notation, and each argument is a separate value
or operator. The following operators are supported:
div Divide current operand by the previous operand
mul Multiply previous and current operands
sub Subtract previous operand from current one
add Add current and previous operands
neg Negate current operand
and if you run e.g. ./rpncalc 3.0 4.0 5.0 sub mul neg, you get the result 3.000000000.
Now, let's add some new operations, ops-sqrt.c:
#include <math.h>
#include "ops.h"
static int do_sqrt(stack *st)
{
double temp;
int retval;
retval = stack_pop(st, &temp);
if (retval)
return retval;
return stack_push(st, sqrt(temp));
}
DEFINE_OP("sqrt", do_sqrt, "Take the square root of the current operand");
Because the Makefile above compiles all C source files beginning with ops- in to the final binary, the only thing you need to do is recompile the source: make clean all. Running ./rpncalc now outputs
Usage: ./rpncalc [ -h | --help ]
./rpncalc RPN-EXPRESSION
Where RPN-EXPRESSION is an expression using reverse
Polish notation, and each argument is a separate value
or operator. The following operators are supported:
sqrt Take the square root of the current operand
div Divide current operand by the previous operand
mul Multiply previous and current operands
sub Subtract previous operand from current one
add Add current and previous operands
neg Negate current operand
and you have the new sqrt operator available.
Testing e.g. ./rpncalc 1 1 1 1 add add add sqrt yields 2.000000000, as expected.

Unknown type name Error in C program

I am working on C program.i got a compiler error of unknown type name even if the type is declared in .h(header file). Given Below declaration and definition for type name extract from the longer code for the sake of simplicity?
//DECLARATION
typedef int DiscrValue, /* discrete attribute value (0 = ?) */
Attribute; /* attribute number, 1..MaxAtt */
typedef union _attribute_value
{
ContValue _cont_val;
DiscrValue _discr_val;
}
AttValue, *DataRec;
String Target, /* name of dependent att */
*AttName, /* att names */
**AttValName; /* att value names */
//DIFINITION
Attribute ClassAtt=0, /* attribute to use as class */
LabelAtt=0, /* attribute containing case label */
CWtAtt=0; /* attribute containing case weight */
DataRec *Case; /* data items */
String Target, /* name of dependent att */
*AttName, /* att names */
**AttValName; /* att value names */
with above given declaration and definition, when I try to compile the program i got errors.
[ERROR]Unknown type name 'Attribute'
[ERROR]Unknown type name 'DataRec'
[ERROR]Unknown type name 'String'
Any help is very much appreciated
**EDIT**
As I requested i put the header file (defns.h) and the source file(global.c) Here below
**define.h**
#define RELEASE "2.08"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <limits.h>
#include <float.h>
#ifdef WIN64
#define WIN32
#endif
#define SMP
#define MAXCPU 8
#if defined WIN32 || defined _CONSOLE
//-----------------------------------
#include <windows.h>
#include <process.h>
#define Thread HANDLE
#define ThreadFn void *
#define BeginThread(t,f,a) t = (Thread) _beginthreadex(NULL, 0,\
(ThreadFn) (*f),\
(PVOID) a, 0, NULL)
#define EndThread _endthreadex(1)
#define ThreadReturn return(0)
#define JoinThread(t) {WaitForSingleObject(t, INFINITE);\
CloseHandle(t);}
#define Flag HANDLE
#define MakeFlag(f,n) f = CreateSemaphore(NULL, 0, n, NULL)
#define DestroyFlag(f) CloseHandle(f)
#define RaiseFlag(f) ReleaseSemaphore(f, 1, NULL)
#define WaitForFlag(f) WaitForSingleObject(f, INFINITE)
#define Mutex HANDLE
#define MakeMutex(m) m = CreateMutex(NULL, FALSE, NULL)
#define DestroyMutex(m) CloseHandle(m)
#define LockMutex(m) WaitForSingleObject(m, INFINITE)
#define UnlockMutex(m) ReleaseMutex(m)
//-----------------------------------
#else
//-----------------------------------
#include <pthread.h>
#include <semaphore.h>
#include <sys/unistd.h>
#ifndef _SC_NPROCESSORS_CONF
#define _SC_NPROCESSORS_CONF _SC_NPROC_CONF
#endif
#define Thread pthread_t
#define ThreadFn void *
#define BeginThread(t,f,a) pthread_create(&t, NULL, f, (void *) a)
#define EndThread pthread_exit(NULL)
#define ThreadReturn return(0)
#define JoinThread(t) pthread_join(t, NULL)
#define Flag sem_t
#define MakeFlag(f,n) sem_init(&f, 0, 0)
#define DestroyFlag(f) sem_destroy(&f)
#define RaiseFlag(f) sem_post(&f)
#define WaitForFlag(f) sem_wait(&f)
#define Mutex pthread_mutex_t
#define MakeMutex(m) pthread_mutex_init(&m, NULL)
#define DestroyMutex(m) pthread_mutex_destroy(&m)
#define LockMutex(m) pthread_mutex_lock(&m)
#define UnlockMutex(m) pthread_mutex_unlock(&m)
//-----------------------------------
#endif
/*************************************************************************/
/* */
/* Constants, macros etc. */
/* */
/*************************************************************************/
#define CUBIST
#define MAXN 20 /* max number neighbors allowing for ties */
#define Nil 0 /* null pointer */
#define false 0
#define true 1
#define Width 80 /* approx max width of output */
#define EXCLUDE 1 /* special attribute status: do not use */
#define SKIP 2 /* do not use in models */
#define DISCRETE 4 /* ditto: collect values as data read */
#define ORDERED 8 /* ditto: ordered discrete values */
#define DATEVAL 16 /* ditto: YYYY/MM/DD or YYYY-MM-DD */
#define STIMEVAL 32 /* ditto: HH:MM:SS */
#define TSTMPVAL 64 /* date time */
#define UNKNOWN 1.5777218104420236e-30 /* unlikely value! */
#define NA 1
#define BrDiscr 1 /* test on discrete attribute */
#define BrThresh 2 /* threshold test on continuous attribute */
#define BrSubset 3 /* subset test on discrete attribute */
#define Plural(n) ((n) != 1 ? "s" : "")
#define AllocZero(N,T) (T *) Pcalloc(N, sizeof(T))
#define Alloc(N,T) AllocZero(N,T) /* for safety */
#define Realloc(V,N,T) V = (T *) Prealloc(V, (N)*sizeof(T))
#define Max(a,b) ((a)>(b) ? a : b)
#define Min(a,b) ((a)<(b) ? a : b)
#define Bit(b) (1 << (b))
#define In(b,s) ((s[(b) >> 3]) & Bit((b) & 07))
#define ClearBits(n,s) memset(s,0,n)
#define CopyBits(n,f,t) memcpy(t,f,n)
#define SetBit(b,s) (s[(b) >> 3] |= Bit((b) & 07))
#define ForEach(v,f,l) for(v=f ; v<=l ; ++v)
#define StatBit(a,b) (SpecialStatus[a]&(b))
#define Exclude(a) StatBit(a,EXCLUDE)
#define Skip(a) StatBit(a,EXCLUDE|SKIP)
#define Discrete(a) (MaxAttVal[a] || StatBit(a,DISCRETE))
#define Continuous(a) (! MaxAttVal[a] && ! StatBit(a,DISCRETE))
#define Ordered(a) StatBit(a,ORDERED)
#define DateVal(a) StatBit(a,DATEVAL)
#define TimeVal(a) StatBit(a,STIMEVAL)
#define TStampVal(a) StatBit(a,TSTMPVAL)
#define NotApplic(c,a) (DVal(c,a)==NA)
#define NotApplicVal(AV) (AV._discr_val==NA)
#define Space(s) (s==' ' || s=='\n' || s=='\r' || s=='\t')
#define SkipComment while ( (c = InChar(f)) != '\n' && c != EOF )
#define Free(x) {free(x); x=Nil;}
#define FreeUnlessNil(p) if((p)!=Nil) free(p)
#define CheckClose(f) if(f) {fclose(f); f=Nil;}
#define Before(n1,n2) (n1->Tested < n2->Tested ||\
n1->Tested == n2->Tested && n1->Cut < n2->Cut)
#define Bound(v,l,h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v))
#define NOFILE 0
#define BADATTNAME 1
#define EOFINATT 2
#define SINGLEATTVAL 3
#define BADATTVAL 4
#define BADNUMBER 5
#define DUPATTNAME 6
#define NOMEM 8
#define TOOMANYVALS 9
#define BADDISCRETE 10
#define NOTARGET 11
#define BADTARGET 12
#define LONGNAME 13
#define HITEOF 14
#define MISSNAME 15
#define BADDATE 16
#define BADTIME 17
#define BADTSTMP 18
#define UNKNOWNATT 19
#define BADDEF1 20
#define BADDEF2 21
#define BADDEF3 22
#define SAMEATT 23
#define BADDEF4 24
#define MODELFILE 30
#define CWTATTERR 31
#define Of stdout
#define Goodbye(x) exit(x)
#define CharWidth(S) ((int) strlen(S))
/*************************************************************************/
/* */
/* Type definitions */
/* */
/*************************************************************************/
typedef unsigned char Boolean, BranchType, *Set;
typedef char *String;
typedef int CaseNo; /* data item number */
typedef int CaseCount; /* count of cases */
typedef int DiscrValue, /* discrete attribute value (0 = ?) */
Attribute; /* attribute number, 1..MaxAtt */
#ifdef USEDOUBLE
typedef double ContValue; /* continuous attribute value */
#define PREC 14 /* precision */
#else
typedef float ContValue; /* continuous attribute value */
#define PREC 7 /* precision */
#endif
/* Attribute values are packed into a union:
DVal = (int) discrete value
CVal = (float) continuous value
SVal = (int) offset in IgnoredVals
Missing and non-applicable values are:
discrete:
not applicable: DVal = NA
missing: DVal = 0
continuous:
not applicable: DVal = NA
missing: CVal = UNKNOWN */
typedef union _attribute_value
{
ContValue _cont_val;
DiscrValue _discr_val;
}
AttValue, *DataRec;
#define CVal(Case,Attribute) Case[Attribute]._cont_val
#define DVal(Case,Attribute) Case[Attribute]._discr_val
#define SVal(Case,Attribute) Case[Attribute]._discr_val
#define Class(Case) Case[ClassAtt]._cont_val
#define PredVal(Case) Case[MaxAtt+1]._cont_val
#define DRef1(Case) Case[MaxAtt+1]._cont_val
#define DRef2(Case) Case[MaxAtt+2]._cont_val
typedef int RuleNo; /* rule number */
typedef struct _condrec
{
BranchType NodeType; /* test type */
Attribute Tested; /* attribute tested */
ContValue Cut; /* threshold (if relevant) */
Set Subset; /* subset (if relevant) */
int TestValue; /* specified outcome of test */
}
CondRec, *Condition;
typedef struct _rulerec
{
RuleNo RNo; /* rule number */
int MNo, /* member number for committee models */
Size; /* number of conditions */
Condition *Lhs; /* conditions themselves */
double *Rhs; /* model given by rule */
CaseCount Cover; /* number of cases covered */
float Mean, /* mean value of cases matching rule */
LoVal, /* lowest value in data */
HiVal, /* highest value in data */
LoLim, /* lower bound on predictions */
HiLim, /* upper bound on predictions */
EstErr; /* estimated error */
}
RuleRec, *CRule;
typedef struct _oldrulerec
{
RuleNo RNo; /* rule number */
int Size; /* number of conditions */
Condition *Lhs; /* conditions themselves */
double *Rhs; /* model given by rule */
CaseCount Cover; /* number of cases covered */
float Mean, /* mean value of cases matching rule */
LoVal, /* lowest value in data */
HiVal, /* highest value in data */
LoLim, /* lower bound on predictions */
HiLim, /* upper bound on predictions */
EstErr; /* estimated error */
}
OldRuleRec;
typedef struct _rulesetrec
{
RuleNo SNRules; /* number of rules */
CRule *SRule; /* rules */
}
RuleSetRec, *RRuleSet;
typedef struct _indexrec *Index;
typedef struct _indexrec
{
Attribute Tested; /* split attribute for KD-tree */
ContValue Cut, /* threshold for continuous atts */
MinDRef[2], /* min reference distances */
MaxDRef[2]; /* max ditto */
CaseNo IFp, ILp; /* first and last item at leaf */
Index *SubIndex; /* subtrees */
}
IndexRec;
typedef struct _nnrec
{
int BestI[MAXN]; /* numbers of best instances */
float BestD[MAXN], /* distances to best instances */
*WorstBest, /* points to worst BestD */
*AttMinD; /* min attribute distance from case */
}
NNEnvRec, *NNEnv;
typedef union _def_val
{
String _s_val; /* att val for comparison */
ContValue _n_val; /* number for arith */
}
DefVal;
typedef struct _def_elt
{
short _op_code; /* type of element */
DefVal _operand; /* string or numeric value */
}
DefElt, *Definition;
typedef struct _elt_rec
{
int Fi, /* index of first char of element */
Li; /* last ditto */
char Type; /* 'B', 'S', or 'N' */
}
EltRec;
#define DefOp(DE) DE._op_code
#define DefSVal(DE) DE._operand._s_val
#define DefNVal(DE) DE._operand._n_val
#define OP_ATT 0 /* opcodes */
#define OP_NUM 1
#define OP_STR 2
#define OP_MISS 3
#define OP_AND 10
#define OP_OR 11
#define OP_EQ 20
#define OP_NE 21
#define OP_GT 22
#define OP_GE 23
#define OP_LT 24
#define OP_LE 25
#define OP_SEQ 26
#define OP_SNE 27
#define OP_PLUS 30
#define OP_MINUS 31
#define OP_UMINUS 32
#define OP_MULT 33
#define OP_DIV 34
#define OP_MOD 35
#define OP_POW 36
#define OP_SIN 40
#define OP_COS 41
#define OP_TAN 42
#define OP_LOG 43
#define OP_EXP 44
#define OP_INT 45
#define OP_END 99
/*************************************************************************/
/* */
/* Function prototypes */
/* */
/*************************************************************************/
void PrintResult(int t);
void PrepareForSMP(void);
void TerminateSMP(void);
ThreadFn ProcessCase(int t);
Boolean ReadName(FILE *f, String s, int n, char ColonOpt);
void GetNames(FILE *Nf);
void ExplicitAtt(FILE *Nf);
int Which(String Val, String *List, int First, int Last);
void FreeNamesData();
int InChar(FILE *f);
void ImplicitAtt(FILE *Nf);
void ReadDefinition(FILE *f);
void Append(char c);
Boolean Expression();
Boolean Conjunct();
Boolean SExpression();
Boolean AExpression();
Boolean Term();
Boolean Factor();
Boolean Primary();
Boolean Atom();
Boolean Find(String S);
int FindOne(String *Alt);
Attribute FindAttName();
void DefSyntaxError(String Msg);
void DefSemanticsError(int Fi, String Msg, int OpCode);
void Dump(char OpCode, ContValue F, String S, int Fi);
void DumpOp(char OpCode, int Fi);
Boolean UpdateTStack(char OpCode, ContValue F, String S, int Fi);
AttValue EvaluateDef(Definition D, DataRec Case);
void GetData(FILE *Df, Boolean Train, Boolean AllowUnknownTarget);
Boolean ReplaceUnknowns(DataRec Case, Boolean *AttMsg);
DataRec GetDataRec(FILE *Df, Boolean Train);
int StoreIVal(String S);
void CheckValue(DataRec Case, Attribute Att);
Boolean OutsideRange(DataRec Case);
void FreeCases(DataRec *Case, CaseNo MaxCase);
void FreeCase(DataRec DVec);
void CheckFile(String Extension, Boolean Write);
void ReadFilePrefix(String Extension);
void ReadHeader();
RRuleSet *GetCommittee(String Extension);
RRuleSet InRules();
CRule InRule();
Condition InCondition();
void FreeCttee(RRuleSet *Cttee);
int ReadProp(char *Delim);
String RemoveQuotes(String S);
Set MakeSubset(Attribute Att);
void BinRecoverDiscreteNames();
RRuleSet BinInRules();
void StreamIn(String S, int n);
void ReleaseRule(CRule R);
void PrintRules(RRuleSet RS, String Msg);
void PrintRule(CRule R);
void PrintCondition(Condition C);
Boolean Satisfies(DataRec CaseDesc, Condition OneCond);
float PredictValue(RRuleSet *Cttee, DataRec CaseDesc, float *ErrLim);
float RuleSetPrediction(RRuleSet RS, DataRec CaseDesc, float *ErrLim);
Boolean Matches(CRule R, DataRec Case);
void InitialiseInstances(RRuleSet *Cttee);
void CopyInstances(void);
float NNEstimate(RRuleSet *Cttee, DataRec Case, NNEnv E, float *ErrLim);
float Distance(DataRec Case1, DataRec Case2, float Thresh);
void CheckDistance(DataRec Case, CaseNo Saved, NNEnv E);
void FindNearestNeighbors(DataRec Case, NNEnv E);
float AverageNeighbors(RRuleSet *Cttee, DataRec Case, NNEnv E,
float *ErrLim);
void ShowNearestNeighbors(int Offset, NNEnv E);
Index BuildIndex(CaseNo Fp, CaseNo Lp);
void ScanIndex(DataRec Case, Index Node, float MinD, NNEnv E);
void SwapInstance(CaseNo A, CaseNo B);
void FreeIndex(Index Node);
void FreeInstances(void);
char ProcessOption(int Argc, char *Argv[], char *Options);
void *Pmalloc(size_t Bytes);
void *Prealloc(void *Present, size_t Bytes);
void *Pcalloc(size_t Number, unsigned int Size);
void FreeVector(void **V, int First, int Last);
void Error(int ErrNo, String S1, String S2);
FILE *GetFile(String Extension, String RW);
int Denominator(ContValue Val);
int FracBase(Attribute Att);
int GetInt(String S, int N);
int DateToDay(String DS);
void DayToDate(int Day, String Date);
int TimeToSecs(String TS);
void SecsToTime(int Secs, String Time);
void SetTSBase(int y);
int TStampToMins(String TS);
void CValToStr(ContValue CV, Attribute Att, String DS);
#ifdef WIN32
double posrint(double);
double rint(double);
#endif
/*************************************************************************/
/* */
/* Text strings */
/* */
/*************************************************************************/
#define T_IgnoreNATarget "*** Ignoring instances with N/A target value\n"
#define T_IgnoreBadTarget "*** Ignoring instances with unknown or N/A"\
" target value\n"
#define T_NoCases "*** No instances with known target values\n"
#define T_ReplaceUnknowns "\n Replacing unknown attribute values:\n"
#define T_NoAppVals "ignoring (no applicable values)"
#define T_By "by"
#define T_Rule "Rule"
#define TX_RInfo(c,p,m,l,h,e) ": [%d cases, mean %.*f, range %.7g to %.7g, "\
"est err %.*f]\n\n",c,p,m,l,h,p,e
#define T_If "if"
#define T_Then "then"
#define T_ElementOf "in"
#define T_InRange "in"
#define T_IsUnknown " is unknown\n"
#define TX_Line(l,f) "\n*** line %d of `%s': ", l, f
#define E_NOFILE(f,e) "cannot open file %s%s\n", f, e
#define E_BADATTNAME "`:' or `:=' expected after attribute name"\
" `%s'\n"
#define E_EOFINATT "unexpected eof while reading attribute `%s'\n"
#define E_SINGLEATTVAL(a,v) "attribute `%s' has only one value `%s'\n",\
a, v
#define E_DUPATTNAME "multiple attributes with name `%s'\n"
#define E_CWTATTERR "case weight attribute must be continuous\n"
#define E_BADATTVAL(v,a) "bad value of `%s' for attribute `%s'\n", v, a
#define E_BADNUMBER(a) "value of `%s' changed to `?'\n", a
#define E_NOMEM "unable to allocate sufficient memory\n"
#define E_TOOMANYVALS(a,n) "too many values for attribute `%s'"\
" (max %d)\n", a, n
#define E_BADDISCRETE "bad number of discrete values for attribute"\
" `%s'\n"
#define E_NOTARGET "target attribute `%s' not found\n"
#define E_BADTARGET "target attribute `%s' is not numeric\n"
#define E_LONGNAME "overlength name: check data file formats\n"
#define E_HITEOF "unexpected end of file\n"
#define E_MISSNAME "missing name or value before `%s'\n"
#define E_BADTSTMP(d,a) "bad timestamp `%s' for attribute `%s'\n", d, a
#define E_BADDATE(d,a) "bad date `%s' for attribute `%s'\n", d, a
#define E_BADTIME(d,a) "bad time `%s' for attribute `%s'\n", d, a
#define E_UNKNOWNATT "unknown attribute name `%s'\n"
#define E_BADDEF1(a,s,x) "in definition of attribute `%s':\n"\
"\tat `%.12s': expect %s\n", a, s, x
#define E_BADDEF2(a,s,x) "in definition of attribute `%s':\n"\
"\t`%s': %s\n", a, s, x
#define E_SAMEATT(a,b) "attribute `%s' is identical to attribute"\
" `%s'\n", a, b
#define E_BADDEF3 "cannot define target attribute `%s'\n"
#define E_BADDEF4 "target attribute appears in definition"\
" of attribute `%s':\n"
#define EX_MODELFILE(f) "file %s incompatible with .names file\n", f
#define E_MFATT "undefined or excluded attribute"
#define E_MFATTVAL "undefined attribute value"
#define E_MFEOF "unexpected eof"
#define T_ErrorLimit "Error limit exceeded\n"
#ifdef _CONSOLE
#define finite(x) _finite(x)
#endif
global.c
Attribute ClassAtt=0, /* attribute to use as class */
LabelAtt=0, /* attribute containing case label */
CWtAtt=0; /* attribute containing case weight */
int MaxAtt, /* max att number */
MaxDiscrVal=3, /* max discrete values for any att */
Precision=2, /* decimal places for target */
MaxLabel=0, /* max characters in case label */
LineNo=0, /* input line number */
ErrMsgs=0, /* errors found */
AttExIn, /* attribute exclusions/inclusions */
TSBase=0, /* base day for time stamps */
Delimiter, /* character at end of name */
NCPU=1; /* number of CPUs */
float ErrReduction=1; /* effect of committee model */
int CaseNo, MaxCase=-1; /* max data item number */
DataRec *Case; /* data items */
DiscrValue *MaxAttVal, /* number of values for each att */
*Modal; /* most frequent value for discr att */
char *SpecialStatus; /* special att treatment */
Definition *AttDef; /* definitions of implicit atts */
String Target, /* name of dependent att */
*AttName, /* att names */
**AttValName; /* att value names */
char *IgnoredVals=0; /* values of labels and ignored atts */
int IValsSize=0, /* size of above */
IValsOffset=0; /* index of first free char */
String FileStem="undefined";
char Fn[512]; /* file name */
FILE *Mf=0; /* file for reading models */
ContValue *AttMean=Nil, /* means of att values */
*AttSD=Nil, /* std dev ditto */
*AttMaxVal=Nil, /* max value in training data */
*AttMinVal=Nil, /* min value ditto */
Ceiling=1E38, /* max allowable global prediction */
Floor=-1E38; /* min allowable global prediction */
int *AttPrec=Nil; /* Attribute precision */
DataRec *Instance=Nil, /* training cases */
Ref[2]; /* reference point */
Index KDTree=Nil; /* index for searching training cases */
CaseNo MaxInstance=-1; /* highest instance */
float *RSPredVal=Nil, /* tabulated RS predictions */
*RSErrLim=Nil; /* tabulated RS error limits */
NNEnvRec GNNEnv; /* global NN environment */
unsigned char *Tested; /* used in BuildIndex */
CaseCount *ValFreq; /* used in BuildIndex */
RRuleSet *CubistModel; /* from .model file */
Boolean USEINSTANCES;
float EXTRAP=0.05, /* allowed extrapolation from models */
SAMPLE=0.0, /* sample training proportion */
MAXD, /* max distance for close neighbors */
GlobalMean=0, /* global mean on training data */
GlobalErrLim; /* estimated global error limit */
int MEMBERS=1, /* models in committee */
NN=5, /* nearest neighbors to use */
KRInit;

implicit declaration of function and undefined reference to

About compile suricata.
In Makefile,when CFLAGS wrap "-Werror-implicit-function-declaration"
I got the error:
detect-engine-siggroup.c: In function ‘SigGroupHeadFree’:
detect-engine-siggroup.c:187:9: error: implicit declaration of function ‘_mm_free’ [-Werror=implicit-function-declaration]
SCFreeAligned(sgh->mask_array);
^
detect-engine-siggroup.c: In function ‘SigGroupHeadBuildHeadArray’:
detect-engine-siggroup.c:1715:5: error: implicit declaration of function ‘_mm_malloc’ [-Werror=implicit-function-declaration]
sgh->mask_array = (SignatureMask *)SCMallocAligned((cnt * sizeof(SignatureMask)), 16);
When I delete "-Werror-implicit-function-declaration" in Makefile,I will got the error:
detect-engine-siggroup.o: In function `SigGroupHeadFree':
/root/suricata/suricata-2.0.9/src/detect-engine-siggroup.c:187: undefined reference to `_mm_free'
detect-engine-siggroup.o: In function `SigGroupHeadBuildHeadArray':
/root/suricata/suricata-2.0.9/src/detect-engine-siggroup.c:1715: undefined reference to `_mm_malloc'
Note:_mm_free and _mm_malloc is define in util-mem.h
Yet,I add some code in the other source file,but not in detect-engine-siggroup.c and util-mem.h.
What's wrong?
in detect-engine-siggroup.c(note I have deleted some redundant code here):
void SigGroupHeadFree(SigGroupHead *sgh)
{
if (sgh == NULL)
return;
SCLogDebug("sgh %p", sgh);
PatternMatchDestroyGroup(sgh);
#if defined(__SSE3__) || defined(__tile__)
if (sgh->mask_array != NULL) {
/* mask is aligned */
SCFreeAligned(sgh->mask_array);
sgh->mask_array = NULL;
}
#endif
if (sgh->head_array != NULL) {
SCFree(sgh->head_array);
sgh->head_array = NULL;
}
if (sgh->match_array != NULL) {
detect_siggroup_matcharray_free_cnt++;
detect_siggroup_matcharray_memory -= (sgh->sig_cnt * sizeof(Signature *));
SCFree(sgh->match_array);
sgh->match_array = NULL;
}
sgh->sig_cnt = 0;
if (sgh->init != NULL) {
SigGroupHeadInitDataFree(sgh->init);
sgh->init = NULL;
}
SCFree(sgh);
detect_siggroup_head_free_cnt++;
detect_siggroup_head_memory -= sizeof(SigGroupHead);
return;
}
in util-mem.h(note I have deleted some redundant code here):
#ifndef __UTIL_MEM_H__
#define __UTIL_MEM_H__
#include "util-atomic.h"
#if CPPCHECK==1
#define SCMalloc malloc
#define SCCalloc calloc
#define SCRealloc realloc
#define SCFree free
#define SCStrdup strdup
#define SCMallocAligned _mm_malloc
#define SCFreeAligned _mm_free
#else /* CPPCHECK */
#if defined(_WIN32) || defined(__WIN32)
#include "mm_malloc.h"
#endif
#if defined(__tile__)
/* Need to define __mm_ function alternatives, since these are SSE only.
*/
#include <malloc.h>
#define _mm_malloc(a,b) memalign((b),(a))
#define _mm_free(a) free((a))
#endif /* defined(__tile__) */
SC_ATOMIC_EXTERN(unsigned int, engine_stage);
/* Use this only if you want to debug memory allocation and free()
* It will log a lot of lines more, so think that is a performance killer */
/* Uncomment this if you want to print memory allocations and free's() */
//#define DBG_MEM_ALLOC
#ifdef DBG_MEM_ALLOC
#define SCFree(a) ({ \
extern uint8_t print_mem_flag; \
if (print_mem_flag == 1) { \
SCLogInfo("SCFree at %p", (a)); \
} \
free((a)); \
})
#else /* !DBG_MEM_ALLOC */
#define SCFree(a) ({ \
free(a); \
})
#if defined(__WIN32) || defined(_WIN32)
#define SCFreeAligned(a) ({ \
_mm_free(a); \
})
#else /* !win */
#define SCFreeAligned(a) ({ \
_mm_free((a)); \
})
#endif /* __WIN32 */
#endif /* DBG_MEM_ALLOC */
#endif /* CPPCHECK */
#endif /* __UTIL_MEM_H__ */
#endif /* DBG_MEM_ALLOC */
#endif /* CPPCHECK */
#endif /* __UTIL_MEM_H__ */
/*********************************************************************/
Now solved the problem,reason is forgetting to #include <pmmintrin.h> /* for SSE3 */
/*********************************************************************/
It looks like you have not included util-mem.h properly. SCFreeAligned seem to expand to _mm_free, but _mm_free doesn't seem to expand. Looking at the header file the definition of _mm_free seem to be dependent on __title__ being defined.
Then the compiler just sees a call to _mm_free which is given an implicit prototype as _mm_free doesn't exist. Then of course _mm_free will not be found during linking.

crypt(): Pointer to integer without cast?

Aargh! Why is the compiler complaining? Thanks for any help!
% gcc -o mine mine.c -lcrypt
mine.c: In function 'main':
mine.c:19:14: warning: assignment makes pointer from integer without a cast [enabled by default]
%
Code:
#define _X_OPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
const char key[] = "hello world";
const char salt[]="01";
const int MAXIMUM_HASH_LENGTH = 2 + 11;
int i=0;
char *hash;
long long hashes = 0L;
while (1) {
hash = crypt(key, salt); /* problem with this line... */
if (hash[2] == '0') {
int leading0s = 0;
leading0s++;
for (i=3; i < MAXIMUM_HASH_LENGTH; i++) {
if (hash[i] != '0') break;
leading0s++;
}
printf("Winner: %s has %d leading zeros.\n",
hash, leading0s);
printf("\t--> Hash %lld.\n\n", hashes);
}
if (hashes != 0 && (hashes % 10000) == 0) {
printf("Hash %d: %s\n", hashes, hash);
}
if (hashes== 1000000) break;
hashes++;
}
return 1000;
}
Try changing "#define _X_OPEN_SOURCE" to "#define _XOPEN_SOURCE".
You should normally specify a number for _XOPEN_SOURCE; valid values include:
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2001 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600 /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
You may prefer to use 700 instead of 600; it depends on your platform(s). However, with the correct spelling, you can simply write #define _XOPEN_SOURCE and it will also define the crypt() for you.
You might also care to note that the exit status is limited to an 8-bit value, so returning 1000 from main() is equivalent to returning 1000 % 256. You also need to fix line 34 of your code:
printf("Hash %d: %s\n", hashes, hash);
should be:
printf("Hash %lld: %s\n", hashes, hash);

C preprocessor macro for returning a string repeated a certain number of times

Does someone know of any C99 preprocessor magic that allows for creating a string consisting of another string repeated N times?
E.g.
STRREP( "%s ", 3 )
becomes
"%s %s %s "
after preprocessing.
The only thing I could think of myself was something like this
#define STRREP( str, N ) STRREP_##N( str )
#define STRREP_0(str) ""
#define STRREP_1(str) str
#define STRREP_2(str) str str
#define STRREP_3(str) str str str
...
which works well, but is ugly as I have to define a macro for each repetition length manually. I want to use it together with variadic macros and the macro returning the number of macro arguments shown here.
Since it's a macro and N is a numeric constant anyway, how about this?
#include <stdio.h>
#define REP0(X)
#define REP1(X) X
#define REP2(X) REP1(X) X
#define REP3(X) REP2(X) X
#define REP4(X) REP3(X) X
#define REP5(X) REP4(X) X
#define REP6(X) REP5(X) X
#define REP7(X) REP6(X) X
#define REP8(X) REP7(X) X
#define REP9(X) REP8(X) X
#define REP10(X) REP9(X) X
#define REP(HUNDREDS,TENS,ONES,X) \
REP##HUNDREDS(REP10(REP10(X))) \
REP##TENS(REP10(X)) \
REP##ONES(X)
int main(void)
{
printf(REP(9,0,7, "*")); // "*" repeated 907 times
printf(REP(0,9,2, "#")); // "#" repeated 92 times
printf(REP(0,0,1, "#")); // "#" repeated 1 times
return 0;
}
My suggestion is to use the boost.
E.g.
#include <stdio.h>
#include <boost/preprocessor/repetition/repeat.hpp>
#define Fold(z, n, text) text
#define STRREP(str, n) BOOST_PP_REPEAT(n, Fold, str)
int main(){
printf("%s\n", STRREP("%s ", 3));//STRREP("%s ", 3) -> "%s %s %s "
return 0;
}
I recently discovered a recursion scheme with the CPP c-preprocessor file inclusion mechanism over the __INCLUDE_LEVEL__ preprocessor literal which is treated automatically - so maybe this algorithm only works for gcc ?!?
The algorithm is conceptually unlimited, it can be extended with additional file indirection.
The herin presented code handles an ITERATION_COUNT from 0-39202
With the comment/uncomment of the ITERATION_SEPARATOR you can
generate N elements, or 1 element with N concatenations, suitable for string repetitions.
The ITERATION_ELEMENT macro is used as the "repetition element"
You can compile the code regulary, without any additional defines. The macro invocation inside the code is idempotent.
An exemplary output:
> gcc iterate.c -o iterate -Wall -s -O3 && ./iterate.exe
0-1591 Counter
1592 Elements
iterate.c:
#include <stdio.h>
#include <inttypes.h>
int main(void) {
const char * preproc_array[] = {
#define ITERATION_COUNT 1592 //0-(199*197-1)39202 (maximum counter)
#define ITERATION_SEPARATOR , //this macro, if active, determines wheather there exits N separate elements otherwise, if outcommented, just 1 element with N concatenations
#define ITERATION_ELEMENT 0-__COUNTER__ Counter\n //the expanded macro as an arbitrary element
#include "iterate.h"
};
return !printf("%s%"PRIu32" Elements",preproc_array[
#ifndef NO_ITERATION_SEPARATOR
__COUNTER__-1
#else
0
#endif
], sizeof(preproc_array)/sizeof(const char *));
}
iterate.h:
#define ITERATION_START 1 //start index of first inclusion
#define ITERATION_LIMIT 199 //conforming to CPP preprocessor manual pg. 54 chapter 11.5, a limit of 200 is set arbitrary
#define ITERATION(...) _ITERATION(__VA_ARGS__)
#define _ITERATION(...) #__VA_ARGS__ ITERATION_SEPARATOR
#ifndef ITERATION_SEPARATOR
#define ITERATION_SEPARATOR
#define NO_ITERATION_SEPARATOR
#endif
//here begins the recursive algorithm via preprocessor file inclusion, enable the warnings if you want to see how it loops through
#if __INCLUDE_LEVEL__ <= ITERATION_COUNT/ITERATION_LIMIT
//~ #warning DIV
#define ITERATION_END ITERATION_COUNT/ITERATION_LIMIT+3 // + offset
#include "loop.h"
#define ITERATION_END ITERATION_LIMIT
#include "loop.h"
#include "iterate.h"
#endif
#if __INCLUDE_LEVEL__ == ITERATION_START
//~ #warning MOD
#define ITERATION_END ITERATION_COUNT%ITERATION_LIMIT+ITERATION_START
#include "loop.h"
#if ITERATION_COUNT % ITERATION_LIMIT
#define ITERATION_END 3 // + offset
#include "loop.h"
#endif
#endif
//end of alogrithm
loop.h:
#if __INCLUDE_LEVEL__ < ITERATION_END
#include "loop.h"
ITERATION(ITERATION_ELEMENT)
#undef ITERATION_END
#endif
Not sure whether it can be done with the macro but you can do it with the function like:
char *strrep(const char *str, int nrep)
{
if (nrep <= 0 || !str) return NULL;
char *buf = malloc(strlen(str) * nrep + 1);
if (!buf) return NULL;
for (int i = 0; i < nrep; ++i) {
strcat(buf, str);
}
return buf;
}
Now you can use it:
char *r = strrep("%s", 3);
if (r) {
...
free(r);
}
UPD: If you want to avoid malloc/free this is a variant of the first code:
/* .h */
#define STRREP_MAX_CHARS 1024
#define STRREP_INIT static char __strrep_buffer[STRREP_MAX_CHARS]
#define STRREP(str, nrep) strrep(str, nrep) ? __strrep_buffer : ""
char *strrep(const char *str, int nrep);
/* .c */
STRREP_INIT;
char *strrep(const char *str, int nrep)
{
if (nrep <= 0 || !str) return 0;
if (strlen(str) * nrep >= STRREP_MAX_CHARS) return 0;
memset(__strrep_buffer, 0, STRREP_MAX_CHARS);
for (int i = 0; i < nrep; ++i) {
strcat(__strrep_buffer, str);
}
return __strrep_buffer;
}
Now:
printf("%s\n", STRREP("%s", 3));
OTOH, this looks even uglier than the first one.
How about something like this?
#define DUP2(str) str str
#define DUP4(str) DUP2(str) DUP2(str)
#define DUP8(str) DUP4(str) DUP4(str)
#define DUP16(str) DUP8(str) DUP8(str)
#define DUP32(str) DUP16(str) DUP16(str)
#define DUP64(str) DUP32(str) DUP32(str)
#define DUP128(str) DUP64(str) DUP64(str)
#define DUP256(str) DUP128(str) DUP128(str)
#define DUP512(str) DUP256(str) DUP256(str)
#define DUP1024(str) DUP512(str) DUP512(str)

Resources