Is there some functions in c which behaves like scanf (taking inputs from the keyboard) while being able to move the cursor in the input by pressing the arrow keys, like in a terminal ?
There are no function in C standard to do that.
You can look at ncurses
In addition to previous suggestions, if you want to do a little work you can "roll your own" using the vt100 escape sequences, which most (probably all) terminal programs continue to support. Here's a small sample program,
#include <stdio.h>
#include <string.h>
#include "vt100.h"
int main ( int argc, char *argv[] )
{
char cupstr[99];
char reply[99];
strcpy(cupstr,_cup(12,25));
printf("%sEnter Data ---> ",cupstr);
fgets(reply,88,stdin);
strcpy(cupstr,_cup(13,25));
printf("%sEchoed Data --> %s\n",cupstr,reply);
}
And the big part is that vt100.h containing all the escape sequences,
/* ------------------------------------------------------------------------- *
VT100.H (c)1989-1999, John Forkosh Associates VT-100 Graphics
* ------------------------------------------------------------------------- */
#define bel printf("\007")
#define esc printf("\033")
#define csi printf("\033[")
#define lscreen printf("\033[?5h")
#define dscreen printf("\033[?5l")
#define rev_vid printf("\033[7m")
#define blink printf("\033[5m")
#define under printf("\033[4m")
#define bold printf("\033[1m")
#define norm_vid printf("\033[0m")
#define wide_vid printf("\033#6")
#define high_vid2 printf("\033#4")
#define high_vid1 printf("\033#3")
#define graphic printf("\033(0")
#define no_graph printf("\033(B")
#define no_window printf("\033[1;24r")
#define no_att printf("\033[0;22;24;25;27m")
#define cup(row,col) printf("\033[%d;%dH",(row),(col))
#define stbm(top,bot) printf("\033[%d;%dr",(top),(bot))
#define ri printf("\033M")
#define el printf("\033[K")
#define ed0 printf("\033[0J")
#define bar graphic;printf("x");no_graph
#define wipe(row,col) cup(row,col);printf("\033[J")
#define clr wipe(0,0);norm_vid
/* ------------------------------------------------------------------------- *
String equivalents ... Note: _cup() and _stbm() only accept literal args.
* ------------------------------------------------------------------------- */
#define _bel "\007"
#define _esc "\033"
#define _csi "\033["
#define _lscreen "\033[?5h"
#define _dscreen "\033[?5l"
#define _rev_vid "\033[7m"
#define _blink "\033[5m"
#define _under "\033[4m"
#define _bold "\033[1m"
#define _norm_vid "\033[0m"
#define _wide_vid "\033#6"
#define _high_vid2 "\033#4"
#define _high_vid1 "\033#3"
#define _graphic "\033(0"
#define _no_graph "\033(B"
#define _no_window "\033[1;24r"
#define _no_att "\033[0;22;24;25;27m"
#define _cup(row,col) "\033[" #row ";" #col "\110"
#define _stbm(top,bot) "\033[" #top ";" #bot "\162"
#define _ri "\033M"
#define _el "\033[K"
#define _ed0 "\033[0J"
#define _bar "\033(0x\033(B"
#define _wipe_clr "\033[0;0H\033[2J"
#define _clr "\033[0;0H\033[2J\033(B\033[0m\033[1;24r"
/* ------------------------------------------------------------------------- */
These escape sequences let you program all the stuff that used to look so cool on vt100's, vt220's, etc, a long, long time ago (but right here in this galaxy).
Related
So, whenever I need to reference certain ASCII control characters I find myself doing junk like this:
#define STX 2
#define ETX 3
Is there some C header file found in most development environments (LINUX probably) that define these constants for me so that I don't have to use magic numbers or define them all the time? Something like <stdint.h>.
I've been writing C code for 35 years and I've never come across such a header file.
The best I can do for you off the top of my head:
1. Using the Linux Documentation Project's manpage source
This file is likely to be present somewhere on your machine; the path I used is where you'll find it on a Debian/Ubuntu install. The list only includes C0 codes, but maybe that's good enough:
$ gunzip -c /usr/share/man/man7/ascii.7.gz |
> awk '$1~/0[0-3][0-7]/{printf "#define C0_%-3s %2d\n", $4, $2}'
#define C0_NUL 0
#define C0_SOH 1
#define C0_STX 2
#define C0_ETX 3
#define C0_EOT 4
#define C0_ENQ 5
#define C0_ACK 6
#define C0_BEL 7
#define C0_BS 8
#define C0_HT 9
#define C0_LF 10
#define C0_VT 11
#define C0_FF 12
#define C0_CR 13
#define C0_SO 14
#define C0_SI 15
#define C0_DLE 16
#define C0_DC1 17
#define C0_DC2 18
#define C0_DC3 19
#define C0_DC4 20
#define C0_NAK 21
#define C0_SYN 22
#define C0_ETB 23
#define C0_CAN 24
#define C0_EM 25
#define C0_SUB 26
#define C0_ESC 27
#define C0_FS 28
#define C0_GS 29
#define C0_RS 30
#define C0_US 31
2. Using the Unicode Character Database.
This includes a lot more, with lots of Unicode control characters, some of them in the astral plane, although obviously you can filter it. It also includes some extra abbreviation names. The file NamedAliases.txt can be downloaded from https://www.unicode.org/Public/14.0.0/ucd/NameAliases.txt or you can grab the entire UCD as a zipped archive at https://www.unicode.org/Public/zipped/14.0.0/
I truncated the output at 60 lines; the entire list is 353 lines.
awk -F\; '$3=="abbreviation"
{printf "#define CTL_%-8s 0x%s\n", $2, $1}' \
UCD/NameAliases.txt
#define CTL_NUL 0x0000
#define CTL_SOH 0x0001
#define CTL_STX 0x0002
#define CTL_ETX 0x0003
#define CTL_EOT 0x0004
#define CTL_ENQ 0x0005
#define CTL_ACK 0x0006
#define CTL_BEL 0x0007
#define CTL_BS 0x0008
#define CTL_HT 0x0009
#define CTL_TAB 0x0009
#define CTL_LF 0x000A
#define CTL_NL 0x000A
#define CTL_EOL 0x000A
#define CTL_VT 0x000B
#define CTL_FF 0x000C
#define CTL_CR 0x000D
#define CTL_SO 0x000E
#define CTL_SI 0x000F
#define CTL_DLE 0x0010
#define CTL_DC1 0x0011
#define CTL_DC2 0x0012
#define CTL_DC3 0x0013
#define CTL_DC4 0x0014
#define CTL_NAK 0x0015
#define CTL_SYN 0x0016
#define CTL_ETB 0x0017
#define CTL_CAN 0x0018
#define CTL_EOM 0x0019
#define CTL_SUB 0x001A
#define CTL_ESC 0x001B
#define CTL_FS 0x001C
#define CTL_GS 0x001D
#define CTL_RS 0x001E
#define CTL_US 0x001F
#define CTL_SP 0x0020
#define CTL_DEL 0x007F
#define CTL_PAD 0x0080
#define CTL_HOP 0x0081
#define CTL_BPH 0x0082
#define CTL_NBH 0x0083
#define CTL_IND 0x0084
#define CTL_NEL 0x0085
#define CTL_SSA 0x0086
#define CTL_ESA 0x0087
#define CTL_HTS 0x0088
#define CTL_HTJ 0x0089
#define CTL_VTS 0x008A
#define CTL_PLD 0x008B
#define CTL_PLU 0x008C
#define CTL_RI 0x008D
#define CTL_SS2 0x008E
#define CTL_SS3 0x008F
#define CTL_DCS 0x0090
#define CTL_PU1 0x0091
#define CTL_PU2 0x0092
#define CTL_STS 0x0093
#define CTL_CCH 0x0094
#define CTL_MW 0x0095
#define CTL_SPA 0x0096
...
A #define's replacement list containing no spaces can be mapped to integers (IDs):
#define ID_double 1
#define ID_float 2
#define ID_long_double 3
#define ID_(x) ID_##x
#define ID(x) ID_(x)
#define T double
T v;
int x = ID(T); /* 1 */
Now consider:
#define T long double
The code above won't compile:
<source>:3:25: error: 'ID_long' undeclared here (not in a function)
Question: is there a way to support spaces?
For example (somehow):
#define REPLACE_SPACES_TO_UNDERSCORES(x) ??
#define ID(x) ID_(REPLACE_SPACES_TO_UNDERSCORES(x))
#define T long double
T v;
int x = ID(T); /* 3 */
The same idea I had in Replace spaces with underscores in a macro? can also be used here, and the dictionary will be much more realistical in size. In the following code on the end, ID(T) is replaced by 3.
// dictionary
#define WORD_long long,
#define WORD_double double,
// ---------------------------------------------
// the classics
#define COMMA(...) ,
#define FIRST(a, ...) a
// apply function f for each argument recursively with tail
#define FOREACHTAIL_1(f,a) f(a,)
#define FOREACHTAIL_2(f,a,...) f(a,FOREACHTAIL_1(f,__VA_ARGS__))
#define FOREACHTAIL_3(f,a,...) f(a,FOREACHTAIL_2(f,__VA_ARGS__))
#define FOREACHTAIL_4(f,a,...) f(a,FOREACHTAIL_3(f,__VA_ARGS__))
#define FOREACHTAIL_N(_4,_3,_2,_1,N,...) \
FOREACHTAIL_##N
#define FOREACHTAIL(f,...) \
FOREACHTAIL_N(__VA_ARGS__,4,3,2,1)(f,__VA_ARGS__)
// if there are two arguments, expand to true. Otherwise false.
#define IFTWO_N(_0,_1,N,...) N
#define IFTWO(true, false, ...) IFTWO_N(__VA_ARGS__, true, false)
// If empty, expand to true, otherwise false.
// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
#define IFEMPTY(true, false, ...) IFTWO(true, false, COMMA __VA_ARGS__ ())
// Join arguments with `_`.
#define JOIN_U(a, b) a##_##b
#define JOIN_TWO_IN(a,b) IFEMPTY(FIRST, JOIN_U, b)(a, b)
#define JOIN_TWO(a,b) JOIN_TWO_IN(a,b)
#define JOIN(...) FOREACHTAIL(JOIN_TWO, __VA_ARGS__)
// Append WORD_ to each argument and join arguments with spaces.
#define WORD_ /* the last one expands to empty */
#define WORDS_TWO(a, b) WORD_##a b
#define WORDS(...) FOREACHTAIL(WORDS_TWO, __VA_ARGS__)
#define REPLACE_SPACES_TO_UNDERSCORES(a) JOIN(WORDS(WORDS(WORDS(WORDS(WORDS(a))))))
// --------------------------------------------
#define ID_double 1
#define ID_float 2
#define ID_long_double 3
#define ID_IN2(x) ID_##x
#define ID_IN(x) ID_IN2(x)
#define ID(x) ID_IN(REPLACE_SPACES_TO_UNDERSCORES(x))
int main() {
#define T long double
T v;
int x = ID(T); /* 3 */
}
I write a bootloader for an AVR XMega Microcontroller and the bootloader got configured by a configuration file:
Config_Bootloader.h
#ifndef CONFIG_BOOTLOADER_H_
#define CONFIG_BOOTLOADER_H_
#include <avr/io.h>
#define BOOTLOADER_INTERFACE &USARTE0
#define BOOTLOADER_BAUD 115200
#define BOOTLOADER_TX 3
#endif /* CONFIG_BOOTLOADER_H_ */
This configuration file is should be preprocessed by another include file to get some register values etc.
Bootloader_Preprocessing.h
#ifndef BOOTLOADER_PREPROCESSING_H_
#define BOOTLOADER_PREPROCESSING_H_
#include <avr/io.h>
#ifdef USARTE0
#if(BOOTLOADER_INTERFACE == &USARTE0)
#define BOOTLOADER_PORT &PORTE
#else
#error "Invalid bootloader interface!"
#endif
#endif
#if(BOOTLOADER_BAUD == 9600)
#define BOOTLOADER_BRREG_VALUE 12
#define BOOTLOADER_SCALE_VALUE 0
#elif(BOOTLOADER_BAUD == 19200)
#define BOOTLOADER_BRREG_VALUE 11
#define BOOTLOADER_SCALE_VALUE -1
#elif(BOOTLOADER_BAUD == 38400)
#define BOOTLOADER_BRREG_VALUE 9
#define BOOTLOADER_SCALE_VALUE -2
#elif(BOOTLOADER_BAUD == 57600)
#define BOOTLOADER_BRREG_VALUE 75
#define BOOTLOADER_SCALE_VALUE -6
#elif(BOOTLOADER_BAUD == 115200)
#define BOOTLOADER_BRREG_VALUE 11
#define BOOTLOADER_SCALE_VALUE -7
#else
#error "Invalid baud rate for bootloader!"
#endif
#endif /* BOOTLOADER_PREPROCESSING_H_ */
I include both files into my Bootloader.h
#ifndef BOOTLOADER_H_
#define BOOTLOADER_H_
#include "Config_Bootloader.h"
#include "Bootloader_Preprocessing.h"
#endif /* BOOTLOADER_H_ */
And I get this errors and warnings:
> #define BOOTLOADER_INTERFACE &USARTE0
operator '&' has no left operand
> #if(BOOTLOADER_INTERFACE == &USARTE0)
in expansion of macro 'BOOTLOADER_INTERFACE'
#error "Invalid bootloader interface!"
So why does the compare of the address doesn´t work?
There is no such thing as an "address" in the preprocessor, therefore they cannot be compared in an #if preprocessor instruction.
See the GCC docs for #IF for details on what it can and can't do. Consult the documentation for the preprocessor you are using, additional/different restrictions may apply (you tagged this as AVR).
It seems that your preprocessor concluded that the operator & has to be the bitwise operator &, which is a binary operator and therefore requires a left operand.
Okay, I have a solution after struggeling with the C preprocessor.
I define the symbol BOOTLOADER_INTERFACE=E,0 in my config and process the input:
#define CATENATE(Prefix, Name) Prefix##Name
#define FIRST_ARG(A, B) A
#define SECOND_ARG(A, B) B
#define MAKE_USART_NAME(Uart) CATENATE(USART, Uart)
#define MAKE_PORT_NAME(Port) CATENATE(PORT, Port)
#define USART_NAME(Name) MAKE_USART_NAME(CATENATE(Name))
#define PORT_NAME(Name) MAKE_PORT_NAME(FIRST_ARG(Name))
The result is the address of the PORT- and USART-Structure, depending on the given USART interface.
I'm trying to use multiple macros in the definition of another macro, but seem to have problems concatenating them together. Here's a very simplified version of what I'm trying to do:
#include <stdio.h>
#define PICK_SET_A
#ifdef PICK_SET_A
#define SET A
#endif
#ifdef PICK_SET_B
#define SET B
#endif
#define ENABLE_VAR_1_A 1
#define ENABLE_VAR_2_A 1
#define ENABLE_VAR_1_B 0
#define ENABLE_VAR_2_B 0
#define MACRO_RESOLVE(var,set) ENABLE_VAR_##var##_##set
#define ENABLE_VAR_1 MACRO_RESOLVE(1, SET)
#define ENABLE_VAR_2 MACRO_RESOLVE(2, SET)
int main(int argc, char **argv) {
fprintf(stdout, "VALUE: %d\n", ENABLE_VAR_1);
return 0;
}
I would expect the result to be 0.
However, I'm getting compile errors because the MACRO_RESOLVE macro isn't resolving the way I expect it to:
$ gcc -o asdf asdf.c
asdf.c:25:36: error: use of undeclared identifier 'ENABLE_VAR_1_SET'
fprintf(stdout, "VALUE: %d\n", ENABLE_VAR_1);
^
asdf.c:20:26: note: expanded from macro 'ENABLE_VAR_1'
#define ENABLE_VAR_1 MACRO_RESOLVE(1, SET)
^
asdf.c:18:32: note: expanded from macro 'MACRO_RESOLVE'
#define MACRO_RESOLVE(var,set) ENABLE_VAR_##var##_##set
^
<scratch space>:229:1: note: expanded from here
ENABLE_VAR_1_SET
^
1 error generated.
So it looks like SET isn't getting expanded when I define ENABLE_VAR_1.
Since you are trying to build a macro name, you need to do enough intermediate expansions along the way for all tokens to expand. See it live here.
#include <stdio.h>
#define PICK_SET_A
#ifdef PICK_SET_A
#define SET A
#endif
#ifdef PICK_SET_B
#define SET B
#endif
#define ENABLE_VAR_1_A 1
#define ENABLE_VAR_2_A 1
#define ENABLE_VAR_1_B 0
#define ENABLE_VAR_2_B 0
#define MACRO_RESOLVE__(M) M
#define MACRO_RESOLVE_(V, S) MACRO_RESOLVE__(ENABLE_VAR_ ## V ##_## S)
#define MACRO_RESOLVE(var,set) MACRO_RESOLVE_(var, set)
#define ENABLE_VAR_1 MACRO_RESOLVE(1, SET)
#define ENABLE_VAR_2 MACRO_RESOLVE(2, SET)
int main(int argc, char **argv) {
fprintf(stdout, "VALUE: %d\n", ENABLE_VAR_1);
return 0;
}
This question already has answers here:
What are the applications of the ## preprocessor operator and gotchas to consider?
(13 answers)
Closed 7 years ago.
I have a set of target macros for which I want to generate aliases based on a choosing macro, like so:
Choosing macro:
#define I2C_MODULE 1
Alias macros (conceptual form):
#define I2C_MODULE_BASE I2C<Value of I2C_MODULE>_BASE
#define I2C_MODULE_NVIC INT_I2C<Value of I2C_MODULE>
Target macros (from an external file out of my control):
#define INT_I2C0 24
#define INT_I2C1 53
...
#define I2C0_BASE 0x40020000
#define I2C1_BASE 0x40021000
...
I wanted to have the preprocessor generate the alias macros I2C_MODULE_BASE and I2C_MODULE_NVIC based on the
choosing macro I2C_MODULE, but after much reading Q1, P1 and many other references I lost track of, I ended up hard-coding their values. Below I show my current working definitions, and then my last failed attempts at generating the macros:
What works:
#define I2C_MODULE 1
#define I2C_MODULE_BASE I2C1_BASE
#define I2C_MODULE_NVIC INT_I2C1
what did not work:
#define I2C_MODULE 1
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
/* Attempt 1 */
#define I2C_MODULE_BASE "I2C" STR(I2C_MODULE) "_BASE"
#define I2C_MODULE_NVIC "INT_I2C" STR(I2C_MODULE)
/* Attempt 2 */
#define _I2C_MODULE_BASE "I2C" STR(I2C_MODULE) "_BASE"
#define _I2C_MODULE_NVIC "INT_I2C" STR(I2C_MODULE)
#define I2C_MODULE_BASE _I2C_MODULE_BASE
#define I2C_MODULE_NVIC _I2C_MODULE_NVIC
EDIT: I expanded upon the accepted answer to get to where I wanted, as follows:
#define PASTE2(a, b) a ## b
#define PASTE3(a, b, c) a ## b ## c
#define _I2C_MODULE_BASE(x) PASTE3(I2C, x, _BASE)
#define _I2C_MODULE_NVIC(x) PASTE2(INT_I2C, x)
#define I2C_MODULE_BASE _I2C_MODULE_BASE(I2C_MODULE)
#define I2C_MODULE_NVIC _I2C_MODULE_NVIC(I2C_MODULE)
This seems to work:
#define I2C_MODULE 1
//Alias macros (conceptual form):
//#define I2C_MODULE_BASE I2C<Value of I2C_MODULE>_BASE
//#define I2C_MODULE_NVIC INT_I2C<Value of I2C_MODULE>
//Target macros (from an external file out of my control):
#define INT_I2C0 24
#define INT_I2C1 53
#define I2C0_BASE 0x40020000
#define I2C1_BASE 0x40021000
#define PASTE2(a, b) a ## b
#define PASTE3(a, b, c) a ## b ## c
#define I2C_MODULE_BASE(x) PASTE3(I2C, x, _BASE)
#define I2C_MODULE_NVIC(x) PASTE2(INT_I2C, x)
extern int i2c_module_base = I2C_MODULE_BASE(I2C_MODULE);
extern int i2c_module_nvic = I2C_MODULE_NVIC(I2C_MODULE);
extern int i2c_module_base_0 = I2C_MODULE_BASE(0);
extern int i2c_module_nvic_0 = I2C_MODULE_NVIC(0);
extern int i2c_module_base_1 = I2C_MODULE_BASE(1);
extern int i2c_module_nvic_1 = I2C_MODULE_NVIC(1);
Sample output (from cpp):
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"
# 21 "xx.c"
extern int i2c_module_base = 0x40021000;
extern int i2c_module_nvic = 53;
extern int i2c_module_base_0 = 0x40020000;
extern int i2c_module_nvic_0 = 24;
extern int i2c_module_base_1 = 0x40021000;
extern int i2c_module_nvic_1 = 53;
It is closely based on my answer to C preprocessor and token concatenation.
There are undoubtedly other ways that the I2C_MODULE_BASE and I2C_MODULE_NVIC macros could be written, but the key points are:
Using the ## token pasting operator (not the # stringifying operator).
Using two levels of macro (for example, I2C_MODULE_BASE and PASTE3).
I suspect that you are writing a I2C driver which can generically handle multiple I2C hardware peripherals in the same micro-controller without rewriting all the same code multiple times.
In that case, what you are really looking for probably is something like this:
#define I2C1 ((volatile uint8_t*)0x12345678) // address of first hw register for I2C1
#define I2C2 ((volatile uint8_t*)0x55555555) // address of first hw register for I2C2
/* map all registers used for I2C, they will have same register layout for every
peripheral no matter which one: */
#define I2C_CONTROL(base) (*(base + 0))
#define I2C_DATA(base) (*(base + 1))
...
// create some dummy typedef to make your functions look nice:
typedef volatile uint8_t* I2C_t;
// define whatever functions you need in the driver:
void i2c_init (IC2_t bus);
void i2c_send (I2C_t bus, const uint8_t* data, size_t n);
...
// implement functions in a bus-independent way:
void i2c_init (IC2_t bus)
{
I2C_CONTROL(bus) = THIS | THAT; // setup registers
}
// caller code:
i2c_init(I2C1);
i2c_init(I2C2);
...
i2c_send(I2C1, "hello", 5);
i2c_send(I2C2, "world", 5);
Just use #if / #else / #endif
#if (I2C_MODULE == 0)
#define I2C_MODULE_BASE I2C0_BASE
#define I2C_MODULE_NVIC INT_I2C0
#elif (I2C_MODULE == 1)
#define I2C_MODULE_BASE I2C1_BASE
#define I2C_MODULE_NVIC INT_I2C1
#else
#error Unknown configuration
#endif