If you don't say much, first look at the operation effect:
>./term input flag 0x00000500 BRKINT not in ICRNL IGNBRK not in IGNCR not in IGNPAR not in IMAXBEL not in INLCR not in INPCK not in ISTRIP not in IUCLC not in IXANY not in IXOFF not in IXON PARMRK not in output flag 0x00000005 BSDLY not in CMSPAR not defined CRDLY not in FFDLY not in NLDLY not in OCRNL not in OFDEL not in OFILL not in OLCUC not in ONLCR ONLRET not in ONOCR not in ONOEOT not defined OPOST OXTABS not defined TABDLY not in VTDLY not in control flag 0x000000bf CBAUDEXT not defined CCAR_OFLOW not defined CCTS_OFLOW not defined CDSR_OFLOW not defined CDTR_IFLOW not defined CIBAUDEXT not defined CIGNORE not defined CLOCAL not in CREAD CRTSCTS not defined CRTS_IFLOW not defined CRTSXOFF not defined CSIZE CSTOPB not in HUPCL not in MDMBUF not defined PARENB not in PAREXT not defined PARODD not in local flag 0x00008a3b ALTWERASE not defined ECHO ECHOCTL not defined ECHOE ECHOK ECHOKE not defined ECHONL not in ECHOPRT not defined EXTPROC not defined FLUSHO not defined ICANON IEXTEN ISIG NOFLSH not in NOKERNINFO not defined PENDIN not defined TOSTOP not in XCASE not in input control char array size 32 cc[VDISCARD=13] = 15 () VDSUSP not defined cc[VEOF=4] = 4 () cc[VEOL=11] = 0 () cc[VEOL2=16] = 0 () cc[VERASE=2] = 127 () VERASE2 not defined cc[VINTR=0] = 3 () cc[VKILL=3] = 21 () cc[VLNEXT=15] = 22 () cc[VQUIT=1] = 28 () cc[VREPRINT=12] = 18 () cc[VSTART=8] = 17 () VSTATUS not defined cc[VSTOP=9] = 19 () cc[VSUSP=10] = 26 () cc[VWERASE=14] = 23 ()
As we all know, through tcgetattr interface and termios structure, we can get the setting information of a terminal device:
struct termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_cc[NCCS]; /* control characters */ };
It's mainly about various types of flag bits. Although you can print them out, at a glance, what do these numbers mean? You need to check the man Manual of the corresponding platform.
This tool can translate binary flag bits into constant macros that can be read by human beings. For example, in the above output, you can see that the input flag bits turn on two flag bits, ICRNL and icon,
The corresponding meanings are "convert input CR to NL" and "make start / stop output control flow work".
Looking at this output, you may have thought about the implementation of the code, which is to try every constant macro. What's the difficulty.
Yes, but considering that the macros defined on different platforms are different, sometimes adding one or two macros may also need to modify the source code, which is so painful!
This little tool solves this pain point. You can specify the macro name to be tested in the configuration file, and then make it~~~
BRKINT ICRNL IGNBRK IGNCR IGNPAR IMAXBEL INLCR INPCK ISTRIP IUCLC IXANY IXOFF IXON PARMRK
BSDLY CMSPAR CRDLY FFDLY NLDLY OCRNL OFDEL OFILL OLCUC ONLCR ONLRET ONOCR ONOEOT OPOST OXTABS TABDLY VTDLY
CBAUDEXT CCAR_OFLOW CCTS_OFLOW CDSR_OFLOW CDTR_IFLOW CIBAUDEXT CIGNORE CLOCAL CREAD CRTSCTS CRTS_IFLOW CRTSXOFF CSIZE CSTOPB HUPCL MDMBUF PARENB PAREXT PARODD
ALTWERASE ECHO ECHOCTL ECHOE ECHOK ECHOKE ECHONL ECHOPRT EXTPROC FLUSHO ICANON IEXTEN ISIG NOFLSH NOKERNINFO PENDIN TOSTOP XCASE
In fact, this is achieved by using awk to read configuration files and automatically generate c code:
1 #! /bin/awk -f 2 # usage: print_flag.awk -v FUNC_NAME=xxx -v MACRO_FILE=xxx 3 # i.e.: print_flag.awk -v FUNC_NAME=output -v MACRO_FILE=oflag.sym 4 BEGIN { 5 printf("#include \"../apue.h\"\n") 6 printf("#include <termios.h>\n") 7 printf("\n") 8 printf("void print_%s_flag (tcflag_t flag)\n", FUNC_NAME) 9 printf("{\n") 10 printf(" printf (\"%s flag 0x%%08x\\n\", flag); \n", FUNC_NAME) 11 FS=":" 12 while (getline < MACRO_FILE > 0) { 13 printf("#ifdef %s\n", $1) 14 printf(" if (flag & %s)\n", $1) 15 printf(" printf (\" %s\\n\"); \n", $1) 16 printf(" else\n") 17 printf(" printf (\" %s not in\\n\"); \n", $1) 18 printf("#else\n") 19 printf(" printf (\" %s not defined\\n\"); \n", $1) 20 printf("#endif\n") 21 } 22 close (MACRO_FILE) 23 exit 24 } 25 END { 26 printf("}") 27 }
The generated c file is similar to this:
1 #include "../apue.h" 2 #include <termios.h> 3 4 void print_input_flag (tcflag_t flag) 5 { 6 printf ("input flag 0x%08x\n", flag); 7 #ifdef BRKINT 8 if (flag & BRKINT) 9 printf (" BRKINT\n"); 10 else 11 printf (" BRKINT not in\n"); 12 #else 13 printf (" BRKINT not defined\n"); 14 #endif 15 #ifdef ICRNL 16 if (flag & ICRNL) 17 printf (" ICRNL\n"); 18 else 19 printf (" ICRNL not in\n"); 20 #else 21 printf (" ICRNL not defined\n"); 22 #endif 23 }
If you look at the generation rules of Makefile again, it will be clearer:
1 all: term 2 3 term: term.o print_iflag.o print_oflag.o print_cflag.o print_lflag.o print_cchar.o apue.o 4 gcc -Wall -g $^ -o $@ 5 6 term.o: term.c ../apue.h 7 gcc -Wall -g -c $< -o $@ 8 9 print_iflag.o: print_iflag.c ../apue.h 10 gcc -Wall -g -c $< -o $@ 11 12 print_iflag.c: print_flag.awk iflag.sym 13 ./print_flag.awk -v FUNC_NAME=input -v MACRO_FILE=iflag.sym > print_iflag.c 14 15 print_oflag.o: print_oflag.c ../apue.h 16 gcc -Wall -g -c $< -o $@ 17 18 print_oflag.c: print_flag.awk oflag.sym 19 ./print_flag.awk -v FUNC_NAME=output -v MACRO_FILE=oflag.sym > print_oflag.c 20 21 print_cflag.o: print_cflag.c ../apue.h 22 gcc -Wall -g -c $< -o $@ 23 24 print_cflag.c: print_flag.awk cflag.sym 25 ./print_flag.awk -v FUNC_NAME=control -v MACRO_FILE=cflag.sym > print_cflag.c 26 27 print_lflag.o: print_lflag.c ../apue.h 28 gcc -Wall -g -c $< -o $@ 29 30 print_lflag.c: print_flag.awk lflag.sym 31 ./print_flag.awk -v FUNC_NAME=local -v MACRO_FILE=lflag.sym > print_lflag.c 32 33 print_cchar.o: print_cchar.c ../apue.h 34 gcc -Wall -g -c $< -o $@ 35 36 print_cchar.c: print_char.awk cchar.sym 37 ./print_char.awk -v FUNC_NAME=control -v MACRO_FILE=cchar.sym > print_cchar.c 38 39 log.o: ../log.c ../log.h 40 gcc -Wall -g -c $< -o $@ 41 42 apue.o: ../apue.c ../apue.h 43 gcc -Wall -g -c $< -o $@ -D__USE_BSD 44 45 clean: 46 @echo "start clean..." 47 -rm -f *.o core.* *.log *~ *.swp term 48 @echo "end clean" 49 50 .PHONY: clean
Specific analysis of the generation process:
1. Generate print ﹐ iflag. C / print ﹐ oflag. C / print ﹐ C flag. C / print ﹐ lflag. C respectively through print ﹐ flag.awk
2. Compile the generated. c into. o files
3. Link the above. o file to generate the final executable file when generating the term tool
Of course, in addition to all kinds of flag bits, the CC ﹐ t CC field is also processed here. It prints every special input character. The principle is similar to the above, so it will not be repeated.
Check the special characters printed. It is found that the characters with subscript 5 / 6 / 7 are missing. Check the definition of header file. Three new definitions have been added to linux
VTIME VMIN VSWTC
Add them to the sym file, recompile and run them. As expected, the new output includes:
cc[VTIME=5] = 0 () cc[VMIN=6] = 1 () cc[VSWTC=7] = 0 ()
This is very helpful for testing on different platforms.