I know macro can return value of custom type:
#define returnVal(type) ({ \
type val; \
val; \
})
I am trying to create a macro which can return custom type pointer by input number. (So it can be dynamic)
// Pseudo code
#define returnPtr(number) ({ \
// if number == 1, return int *val \
// if number == 2, return int **val \
// if number == 3, return int ***val \
})
I tried some approaches but it doesn't work:
#define returnPtr(number) ({ \
type = number == 1 ? int * : number == 2 ? int ** \
: int ***; \
type val; \
val; \
})
How to return custom type pointer by input number in a macro function?
If the macro argument is just a literal 0, 1, etc., this can be done by pasting it (with ##) to form a name (like TYPE0, TYPE1, etc.) that is defined as a macro to be replaced with a type name. The following code shows a way to do this. Note that writing code like this is generally bad practice absent compelling reason.
#include <stdio.h>
#define TYPE1 int *
#define TYPE2 int **
#define TYPE3 int ***
#define Kludge(number) (TYPE##number) {0}
#define Demo(number) \
_Generic(Kludge(number), \
int *: "int *", \
int **: "int **", \
int ***: "int ***", \
default: "something else")
int main(void)
{
puts(Demo(1));
puts(Demo(2));
puts(Demo(3));
}
Output:
int *
int **
int ***
if (termAttributes.c_lflag & OPOST)
puts("c_lflag = OPOST");
if (termAttributes.c_lflag & OLCUC)
puts("c_lflag = OLCUC");
I have some code like the above. I want to simplify it as something like this.
TCFLAGPRINT(termAttributes, c_lflag, OPOST)
TCFLAGPRINT(termAttributes, c_lflag, OLCUC)
Could anybody show how to define TCFLAGPRINT?
Here is one way to do it:
#define TCFLAGPRINT(tio, field, flag) \
do { \
if ((tio).field & (flag)) \
puts(#field " = " #flag); \
} while (0)
The do { } while (0) wrapper is a common idiom that forces you to add a semicolon to the end of the macro call. (In this case, it also prevents you adding else after the macro call.)
The # operator before a macro parameter name in the replacement text of the function-like macro converts the parameter name to a string literal.
The #field " = " #flag is concatenating three string literals into a single string constant.
I print bit masks quite a lot so I've come up with my own mechanism for this.
I use a struct table and some functions.
I've pulled in some of my code from a library to illustrate:
#include <stdio.h>
#include <string.h>
#include <termios.h>
typedef struct {
unsigned long tgb_val;
const char *tgb_tag;
const char *tgb_reason;
} tgb_t;
#define TGBEOT \
{ .tgb_tag = NULL }
#define TGBMORE(_tgb) \
_tgb->tgb_tag != NULL
#define _TGBFORALL(_tgb) \
; TGBMORE(_tgb); ++_tgb
#define TGBFORALL(_tga,_tgb) \
_tgb = _tga; TGBMORE(_tgb); ++_tgb
#define TGBDUAL(_sym) \
{ .tgb_val = _sym, .tgb_tag = #_sym },
tgb_t lflag_tgb[] = {
TGBDUAL(OPOST)
TGBDUAL(OLCUC)
TGBEOT
};
// tgbmskdcd -- decode mask value
char *
tgbmskdcd(char *buf,const tgb_t *tgb,unsigned long val)
{
const char *tag;
int sep;
char *bp;
int len;
bp = buf;
*bp = 0;
sep = 0;
for (TGBFORALL(tgb,tgb)) {
if ((val & tgb->tgb_val) == 0)
continue;
if (sep)
*bp++ = ' ';
sep = 1;
tag = tgb->tgb_tag;
len = strlen(tag);
strcpy(bp,tag);
bp += len;
}
return buf;
}
int
main(void)
{
struct termios term;
char buf[100];
tcgetattr(1,&term);
printf("c_lflag: %s\n",tgbmskdcd(buf,lflag_tgb,term.c_lflag));
return 0;
}
Here's the output:
c_lflag: OPOST OLCUC
Consider the following struct and functions
typedef struct __attribute__((__packed__)) req_file {
uint32_t start_pos;
uint32_t byte_count;
uint16_t name_len;
} req_file;
void req_file_hton(req_file *d){
d->name_len = htons(d->name_len);
d->start_pos = htonl(d->start_pos);
d->byte_count = htonl(d->byte_count);
}
void req_file_ntoh(req_file *d){
d->name_len = ntohs(d->name_len);
d->start_pos = ntohl(d->start_pos);
d->byte_count = ntohl(d->byte_count);
}
The above code is tedious to write for a lot of structs with many fields. I would like to configure the name and the fields of the struct once, and have the functions struct_name_hton and struct_name_ntoh generated for me. I have tried to play with x macros a little but had bad luck. A portable C preprocessor solution will be highly appreciated (not C++).
Well, that's easy.
#include <stdint.h>
#include <arpa/inet.h>
/* the NETSTRUCT library ------------------------------- */
// for uint32_t
#define NETSTRUCT_dec_uint32_t(n) uint32_t n;
#define NETSTRUCT_hton_uint32_t(n) t->n = htonl(t->n);
#define NETSTRUCT_ntoh_uint32_t(n) t->n = ntohl(t->n);
// for uint16_t
#define NETSTRUCT_dec_uint16_t(n) uint16_t n;
#define NETSTRUCT_hton_uint16_t(n) t->n = htons(t->n);
#define NETSTRUCT_ntoh_uint16_t(n) t->n = ntohs(t->n);
// dec hton ntoh switch
#define NETSTRUCT_dec(type, name) NETSTRUCT_dec_##type(name)
#define NETSTRUCT_hton(type, name) NETSTRUCT_hton_##type(name)
#define NETSTRUCT_ntoh(type, name) NETSTRUCT_ntoh_##type(name)
// calls NETSTRUCT_mod
#define NETSTRUCT1(mod, a) NETSTRUCT_##mod a
#define NETSTRUCT2(mod, a, ...) NETSTRUCT1(mod, a) NETSTRUCT1(mod, __VA_ARGS__)
#define NETSTRUCT3(mod, a, ...) NETSTRUCT1(mod, a) NETSTRUCT2(mod, __VA_ARGS__)
#define NETSTRUCT4(mod, a, ...) NETSTRUCT1(mod, a) NETSTRUCT3(mod, __VA_ARGS__)
// TO DO: all up to NETSTRUCT64
// variadic macro overload
#define NETSTRUCT_GET(_1,_2,_3,_4,NAME,...) NAME
// Overlads VA_ARGS with specified mod
#define NETSTRUCT_IN(mod, ...) \
NETSTRUCT_GET(__VA_ARGS__, NETSTRUCT4, NETSTRUCT3, NETSTRUCT2, NETSTRUCT1) \
(mod, __VA_ARGS__)
// entrypoint of out library
#define NETSTRUCT(name, ...) \
\
struct name { \
NETSTRUCT_IN(dec, __VA_ARGS__) \
} __attribute__((__packed__)); \
\
void name##_hton(struct name *t) { \
NETSTRUCT_IN(hton, __VA_ARGS__) \
} \
\
void name##_ntoh(struct name *t) { \
NETSTRUCT_IN(ntoh, __VA_ARGS__) \
}
/* -------------------------------------------------------- */
// adding custom type
#define NETSTRUCT_dec_uint8_t_arr_8(n) uint8_t n[8];
#define NETSTRUCT_hton_uint8_t_arr_8(n) do{}while(0);
#define NETSTRUCT_ntoh_uint8_t_arr_8(n) do{}while(0);
NETSTRUCT(reg_file,
(uint32_t, start_pos),
(uint32_t, byte_count),
(uint16_t, name_len),
(uint8_t_arr_8, example_custom_array)
);
int main() {
struct reg_file t;
reg_file_hton(&t);
reg_file_ntoh(&t);
}
I have written the mactos so it's easy to add another function, most probably void name##serialize(char *in) and void name##deserialize(const char *out). The design can be slightly refactored so that type callbacks NETSTRUCT_dec_* take two or even unknown number of arguments with ex. NETSTRUCT(name, (type_callback_suffix, (arguments, arguments2))).
#edit added custom array type example and some lines order changing.
IMHO, you should use a raw buffer for input / output. This is by far more portable (and safer) than guessing the way a compiler will order the fields or the structure on each system.
In addition, this would allow you to pack/unpack data without worrying about byte order or memory alignment.
The macros in this example code were extracted from the facil.io framework header:
/** Reads an unaligned network ordered byte stream to a 16 bit number. */
#define fio_str2u16(c) \
((uint16_t)(((uint16_t)(((uint8_t *)(c))[0]) << 8) | \
(uint16_t)(((uint8_t *)(c))[1])))
/** Reads an unaligned network ordered byte stream to a 32 bit number. */
#define fio_str2u32(c) \
((uint32_t)(((uint32_t)(((uint8_t *)(c))[0]) << 24) | \
((uint32_t)(((uint8_t *)(c))[1]) << 16) | \
((uint32_t)(((uint8_t *)(c))[2]) << 8) | \
(uint32_t)(((uint8_t *)(c))[3])))
/** Writes a local 16 bit number to an unaligned buffer in network order. */
#define fio_u2str16(buffer, i) \
do { \
((uint8_t *)(buffer))[0] = ((uint16_t)(i) >> 8) & 0xFF; \
((uint8_t *)(buffer))[1] = ((uint16_t)(i)) & 0xFF; \
} while (0);
/** Writes a local 32 bit number to an unaligned buffer in network order. */
#define fio_u2str32(buffer, i) \
do { \
((uint8_t *)(buffer))[0] = ((uint32_t)(i) >> 24) & 0xFF; \
((uint8_t *)(buffer))[1] = ((uint32_t)(i) >> 16) & 0xFF; \
((uint8_t *)(buffer))[2] = ((uint32_t)(i) >> 8) & 0xFF; \
((uint8_t *)(buffer))[3] = ((uint32_t)(i)) & 0xFF; \
} while (0);
void req_file_read(req_file *d, unsigned char * buffer){
d->byte_count = fio_str2u32(buffer);
d->start_pos = fio_str2u32(buffer + 4);
d->name_len = fio_str2u16(buffer + 8);
}
void req_file_write(unsigned char * buffer, req_file *d){
fio_u2str32(buffer, d->byte_count);
fio_u2str32(buffer + 4, d->start_pos);
fio_u2str16(buffer + 8, d->name_len);
}
This makes it far easier to handle unaligned memory access as well as network byte ordering on any system. The binary based math makes this both portable and space efficient.
EDIT (X-macros)
As per the comments and concerns raised by Lightness Races in Orbit, here's a header file with X-macros that could be used to automatically create X_read / X_write inline functions.
The downside of serialization is that the byte offset for the raw buffer should be provided when declaring the struct using the macros.
In this example, the same header is included a number of times with different results. Also, the read/write functions don't have to be inlined, it's just an example.
Here's the header:
/* note there's NO include guard in the header file */
#ifndef H__FACIL_IO_MACROS
#define H__FACIL_IO_MACROS
/** Reads an unaligned network ordered byte stream to a 16 bit number. */
#define fio_str2u16(c) \
((uint16_t)(((uint16_t)(((uint8_t *)(c))[0]) << 8) | \
(uint16_t)(((uint8_t *)(c))[1])))
/** Reads an unaligned network ordered byte stream to a 32 bit number. */
#define fio_str2u32(c) \
((uint32_t)(((uint32_t)(((uint8_t *)(c))[0]) << 24) | \
((uint32_t)(((uint8_t *)(c))[1]) << 16) | \
((uint32_t)(((uint8_t *)(c))[2]) << 8) | \
(uint32_t)(((uint8_t *)(c))[3])))
/** Writes a local 16 bit number to an unaligned buffer in network order. */
#define fio_u2str16(buffer, i) \
do { \
((uint8_t *)(buffer))[0] = ((uint16_t)(i) >> 8) & 0xFF; \
((uint8_t *)(buffer))[1] = ((uint16_t)(i)) & 0xFF; \
} while (0);
/** Writes a local 32 bit number to an unaligned buffer in network order. */
#define fio_u2str32(buffer, i) \
do { \
((uint8_t *)(buffer))[0] = ((uint32_t)(i) >> 24) & 0xFF; \
((uint8_t *)(buffer))[1] = ((uint32_t)(i) >> 16) & 0xFF; \
((uint8_t *)(buffer))[2] = ((uint32_t)(i) >> 8) & 0xFF; \
((uint8_t *)(buffer))[3] = ((uint32_t)(i)) & 0xFF; \
} while (0);
/* convert SERIAL_STRUCT_NAME to actual name */
#define SERIAL_STRUCT_MAKE(struct_name) SERIAL_STRUCT_MAKE2(struct_name)
#endif
#if SERIALIZE_TYPE /* create the type */
#undef SERIALIZE_TYPE
#undef SERIAL_STRUCT_FIELD
#define SERIAL_STRUCT_FIELD(name, bits, pos) uint##bits##_t name
#undef SERIAL_STRUCT_MAKE2
#define SERIAL_STRUCT_MAKE2(struct_name) \
typedef struct { \
SERIAL_STRUCT_FIELDS; \
} struct_name##_s;
/* perform macros */
SERIAL_STRUCT_MAKE(SERIAL_STRUCT_NAME)
#elif SERIALIZE_READ /* create reader function */
#undef SERIALIZE_READ
#undef SERIAL_STRUCT_FIELD
#define SERIAL_STRUCT_FIELD(name, bits, pos) \
dest->name = fio_str2u##bits((src + (pos)))
#undef SERIAL_STRUCT_MAKE2
#define SERIAL_STRUCT_MAKE2(struct_name) \
inline static void struct_name_read(struct_name##_s *dest, \
unsigned char *src) { \
SERIAL_STRUCT_FIELDS; \
}
/* perform macros */
SERIAL_STRUCT_MAKE(SERIAL_STRUCT_NAME)
#elif SERIALIZE_WRITE /* create writer function */
#undef SERIALIZE_WRITE
#undef SERIAL_STRUCT_FIELD
#define SERIAL_STRUCT_FIELD(name, bits, pos) \
fio_u2str##bits((dest + (pos)), src->name)
#undef SERIAL_STRUCT_MAKE2
#define SERIAL_STRUCT_MAKE2(struct_name) \
inline static void struct_name##_write(unsigned char *dest, \
struct_name##_s *src) { \
SERIAL_STRUCT_FIELDS; \
}
/* perform macros */
SERIAL_STRUCT_MAKE(SERIAL_STRUCT_NAME)
#endif
In the implementation file, the information might look like this (again, the inline approach could be altered):
/* will produce req_file_s as the struct name, but you can change that */
#define SERIAL_STRUCT_NAME req_file
#define SERIAL_STRUCT_FIELDS \
SERIAL_STRUCT_FIELD(start_pos, 32, 0); \
SERIAL_STRUCT_FIELD(byte_count, 32, 4); \
SERIAL_STRUCT_FIELD(name_len, 16, 8)
#define SERIALIZE_TYPE 1
#include "serialize.h"
#define SERIALIZE_READ 1
#include "serialize.h"
#define SERIALIZE_WRITE 1
#include "serialize.h"
This could be adjusted so SERIALIZE_TYPE also declares the functions (without defining them), and the functions aren't inlined (so only the implementation file includes the header 3 times per type.
You could adapt Antony Polukhin's magic_get library, to be able to convert any (arbitrary) structure into a different byte order - just like it can now print any arbitrary structure to an ostream.
xmacros work. The trick is to use token pasting and aliasing of the functions depending on the type:
#define htonuint32_t htonl
#define htonuint16_t htons
#define ntohuint32_t ntohl
#define ntohuint16_t ntohl
#define DEF_FIELDS \
DEF_FIELD(uint32_t,start_pos); \
DEF_FIELD(uint32_t,byte_count); \
DEF_FIELD(uint16_t,name_len)
#define DEF_FIELD(t,v) t v
typedef struct __attribute__((__packed__)) req_file {
DEF_FIELDS;
} req_file;
#undef DEF_FIELD
#define DEF_FIELD(t,v) d->v = hton##t(d->v)
void req_file_hton(req_file *d) {
DEF_FIELDS;
}
#undef DEF_FIELD
#define DEF_FIELD(t,v) d->v = ntoh##t(d->v)
void req_file_hton(req_file *d) {
DEF_FIELDS;
}
pre-processed code (reformatted for clearer display):
typedef struct __attribute__((__packed__)) req_file {
uint32_t start_pos;
uint32_t byte_count;
uint16_t name_len;
} req_file;
void req_file_hton(req_file *d) {
d->start_pos = htonl(d->start_pos);
d->byte_count = htonl(d->byte_count);
d->name_len = htons(d->name_len);
}
void req_file_hton(req_file *d) {
d->start_pos = ntohl(d->start_pos);
d->byte_count = ntohl(d->byte_count);
d->name_len = ntohl(d->name_len);
}
If you have more than one structure, you can complexify the macro system to be able to generate all the structs & functions. Example with 2 different structures:
#define htonuint32_t htonl
#define htonuint16_t htons
#define ntohuint32_t ntohl
#define ntohuint16_t ntohl
#define DEF_FIELDS_req_file \
DEF_FIELD(uint32_t,start_pos); \
DEF_FIELD(uint32_t,byte_count); \
DEF_FIELD(uint16_t,name_len)
#define DEF_FIELDS_other_file \
DEF_FIELD(uint32_t,foo_pos); \
DEF_FIELD(uint32_t,char_count); \
DEF_FIELD(uint16_t,bar_len)
#define STRUCT_DEF(s) \
START_DECL(s) \
DEF_FIELDS_##s; \
END_DECL(s)
#define START_DECL(s) typedef struct __attribute__((__packed__)) s {
#define END_DECL(s) } s
#define DEF_FIELD(t,v) t v
STRUCT_DEF(req_file);
STRUCT_DEF(other_file);
#undef DEF_FIELD
#undef START_DECL
#undef END_DECL
#define DEF_FIELD(t,v) d->v = hton##t(d->v)
#define START_DECL(s) void s##_hton(s *d) {
#define END_DECL(s) }
STRUCT_DEF(req_file);
STRUCT_DEF(other_file);
#undef DEF_FIELD
#undef START_DECL
#define DEF_FIELD(t,v) d->v = ntoh##t(d->v)
#define START_DECL(s) void s##_ntoh(s *d) {
STRUCT_DEF(req_file);
STRUCT_DEF(other_file);
result:
typedef struct __attribute__((__packed__)) req_file { uint32_t start_pos; uint32_t byte_count; uint16_t name_len; } req_file;
typedef struct __attribute__((__packed__)) other_file { uint32_t foo_pos; uint32_t char_count; uint16_t bar_len; } other_file;
void req_file_hton(req_file *d) { d->start_pos = htonl(d->start_pos); d->byte_count = htonl(d->byte_count); d->name_len = htons(d->name_len); };
void other_file_hton(other_file *d) { d->foo_pos = htonl(d->foo_pos); d->char_count = htonl(d->char_count); d->bar_len = htons(d->bar_len); };
void req_file_ntoh(req_file *d) { d->start_pos = ntohl(d->start_pos); d->byte_count = ntohl(d->byte_count); d->name_len = ntohl(d->name_len); };
void other_file_ntoh(other_file *d) { d->foo_pos = ntohl(d->foo_pos); d->char_count = ntohl(d->char_count); d->bar_len = ntohl(d->bar_len); };
I am trying to simulate Switch statement using macros in my Header file (.h) .
I have some predefined macros:
#define MULTIPLY_BY_1 1
#define MULTIPLY_BY_10 2
#define MULTIPLY_BY_100 3
#define MULTIPLY_BY_1000 4
#define CHOSEN_FACTOR MULTIPLY_BY_100
I have a const result that takes a value according to CHOSEN_FACTOR (The user will define this macro). I am in the header file and I want to "simulate" the switch statement like this:
switch(CHOSEN_VALUE)
{
case MULTIPLY_BY_1:
const uint16_t result = 5;
break;
case MULTIPLY_BY_10:
const uint16_t result = 50;
break;
case MULTIPLY_BY_100:
const uint16_t result = 500;
break;
case MULTIPLY_BY_1000:
const uint16_t result = 50000;
break;
default:
break;
}
EDIT:
In the source file (.c), I want to use result like this:
uint16_t foo(void)
{
uint16_t myFoo = getMyFooValue();
return result * myFoo;
}
Is there any macros-based-solution to so ? Is there a more optimised approach to get the same result ?
Like in this answer suggests, i would suggest you to use enum for getting the selected value and based on the selection with the enum type, return the macro that you have specified. To do that, you can create a function and get the correct macro as shown below.
typedef enum {
MULTIPLY_BY_1
MULTIPLY_BY_10
MULTIPLY_BY_100
MULTIPLY_BY_1000
}multiplier_t;
uint16_t foo(multiplier_t multiplier)
{
switch (multiplier) {
case MULTIPLY_BY_1:
return 1;
case MULTIPLY_BY_10:
return 2;
case MULTIPLY_BY_100:
return 3;
case MULTIPLY_BY_1000:
return 4;
}
return 0; // just in case no code matches
}
Hope this helps you.
Assuming I understand what you're asking for, I think you're looking for something like this:
#define INIT_FACTOR(var, value) \
#ifdef CHOSEN_FACTOR \
#if CHOSEN_FACTOR == MULTIPLY_BY_1 \
const uint16_t var = value \
#elif CHOSEN_FACTOR == MULTIPLY_BY_10 \
const uint16_t var = value * 10 \
#elif CHOSEN_FACTOR == MULTIPLY_BY_100 \
const uint16_t var = value * 100 \
#elif CHOSEN_FACTOR == MULTIPLY_BY_1000 \
const uint16_t var = value * 1000 \
#endif \
#else \
const uint16_t var = value \
#endif
This will define a macro named INIT_FACTOR that takes two arguments, the name of the variable to define and the starting value. You'd add it in the body of your code as
INIT_FACTOR(result, 5);
and then, if CHOSEN_FACTOR is MULTIPLY_BY_100, that line would expand to
const uint16_t result = 5 * 100;
If CHOSEN_FACTOR is not defined, that line expands to
const uint16_t result = 5;
Remember that macro substitution happens at compile time, not run time. If you want a run time solution, this isn't it.
Selection in the preprocessor can be done by using a helper macro to expand a parameter and then pasting it with a token to kludge a look-up table:
#include <stdio.h>
int main(void)
{
#define MULTIPLY_BY_1 1
#define MULTIPLY_BY_10 2
#define MULTIPLY_BY_100 3
#define MULTIPLY_BY_1000 4
#define CHOSEN_FACTOR MULTIPLY_BY_100
#define Foo1 1
#define Foo2 10
#define Foo3 100
#define Foo4 1000
#define FooHelper(x) Foo##x
#define Foo(x) FooHelper(x)
printf("%d\n", Foo(CHOSEN_FACTOR));
}
Preprocessor abuse of this sort should be generally avoided and likely is not needed for the actual problem that motivated this question.
Thank you all for your answers. I was looking for a specific solution and I guess I found it.
#define MULTIPLY_BY_1 0
#define MULTIPLY_BY_10 1
#define MULTIPLY_BY_100 2
#define MULTIPLY_BY_1000 3
const struct
{
uint8_t index;
uint16_t value;
}myArray[] = {
{MULTIPLY_BY_1, 1},
{MULTIPLY_BY_10, 10},
{MULTIPLY_BY_100, 100},
{MULTIPLY_BY_1000, 1000}
};
#define CHOSEN_VALUE MULTIPLY_BY_10
const uint16_t result = myArray[CHOSEN_VALUE].value;
void foo(void)
{
printf("%d", result); // 10
}
Im trying to create a preprocessor macro to allocate and free memory for matrix/vector of any data type. Here is what I have so far:
#ifndef H_ARRAY_H
#define H_ARRAY_H
#include "xmalloc.h"
#define make_vector(v,n) (v = xmalloc( (n) * sizeof *(v))
#define free_vector(v) do { free(v) ; v = NULL; } while(0)
#define make_matrx(a , m , n) do { \
size_t make_matrix_loop_counter; \
make_vector(a, (m) + 1); \
for ( make_matrix_loop_counter = 0; make_matrix_loop_counter < (m) ; make_matrix_loop_counter++) \
make_vector((a)[make_matrix_loop_counter], (n)); \
(a)[m] = NULL; \
} while (0)
#define free_matrix(a) do { \
if (a != NULL){ \
size_t make_matrix_loop_counter; \
for (make_matrix_loop_counter = 0 ; (a) [make_matrix_loop_counter] != NULL; make_matrix_loop_counter++) \
free_vector((a)[make_matrix_loop_counter]); \
free_vector(a); \
a != NULL; \
} \
} while (0)
But when I try to construct a matrix it spits out an error "implicit declaration of function ‘make_matrix’".
Any suggestions.
PS: xmalloc.h allocate space
Are you sure your MACRO name should read make_matrx instead of make_matrix?
You need to correct the macro name spelling. Otherwise, when you use make_matrix() in your code, it does not find a corresponding function.