Lemon parser assertion failure if a set has only one entry - sqlite

This might be my misunderstanding of how parsers reduce rather than a potential bug in SQLite's lemon parser. I have been experimenting with simple grammars for a database input file. The database consists of a list of at least one entry sets, things like "commands", or "maps" or...
Here's a grammar that does not work - I have started creating the entry sets and so far all I have is a "command":
database ::= entrylist.
entrylist ::= entrylist entryset.
entrylist ::= entryset.
entryset ::= command.
/* Commands are in the form %command [arguments] \n */
command ::= CMDNAME cmdargs EOL.
cmdargs ::= cmdargs cmdarg.
cmdargs ::= .
cmdarg ::= INTEGER.
cmdarg ::= TEXT.
If I run this with a test program that just feeds in tokens I get:
$ test
Debug: Input 'CMDNAME'
Debug: Shift 'CMDNAME', go to state 3
Debug: Return. Stack=[CMDNAME]
Debug: Input 'INTEGER'
Assertion failed: stateno <= YY_SHIFT_COUNT, file testpar.c, line 513
If I give the entryset an additional alternative:
entryset ::= command.
entryset ::= map.
...
map ::= MAPNAME EOL.
then the whole thing works as expected. I think perhaps you aren't allowed create a situation where a::=b and b::=c. You must have b ::= c | d at the very least. I'd like to understand if this is my mistake in understanding.

Lemon compresses the shift table to remove default actions from the end of the table. Presumably, default actions should be handled elsewhere but they aren't. Your example happens to have default actions so the table is compressed, YY_MAX_SHIFT and YY_SHIFT_COUNT are out of sync, and the assert is triggered.
In lemon.c, around line 4235, you can comment out this line:
while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
to prevent compression and to prevent the bug.
Generated code with compression:
#define YY_MAX_SHIFT 3
#define YY_SHIFT_COUNT (2)
#define YY_SHIFT_USE_DFLT (13)
static const unsigned char yy_shift_ofst[] = {
/* 0 */ 7, 1, 6,
};
Generated code without compression:
#define YY_MAX_SHIFT 3
#define YY_SHIFT_COUNT (3)
#define YY_SHIFT_USE_DFLT (13)
static const unsigned char yy_shift_ofst[] = {
/* 0 */ 7, 1, 6, 13,
};
I submitted the details to the SQLite mailing list earlier this year but nothing has happened yet. The correct solution is probably to continue compressing but handle default actions in the template.

Bug logged to SQLite mailing list:
http://www.mail-archive.com/sqlite-users#mailinglists.sqlite.org/msg99712.html
http://www.mail-archive.com/sqlite-users#mailinglists.sqlite.org/msg99716.html

Related

why the ROM designed from distributed memory block in vivado can't work?

I am trying to use the Distributed Memory Generator presented by vivado to store some data. But the simulation out of the ROM is always 'xxx'.
Here's my IP setting:I named it temp. Memory config: Depth=160, width=12, ROM.
Port config: input options: registered
Here's my testbench:
`timescale 1ns/1ps
module tb();
reg clk;
reg [6:0] a;
wire [11:0] out;
initial
begin
clk <= 0;
a <= 7'b0000000;
end
always #5 clk <= ~clk;
always #20 a <= a + 1;
temp u (.a(a), .clk(clk), .spo(out));
defparam u.inst.C_READ_MIF = "temp.mif";//initial ROM
endmodule
DEPTH = 160;
WIDTH = 12;
ADDRESS_RADIX = BIN;
DATA_RADIX = BIN;
CONTENT
BEGIN
0:100000000010;
1:100000000100;
10:000000000011;
11:100000000001;
100:100000001011;
101:000000000001;
110:000000000001;
111:000000000000;
1000:000000000000;
1001:100000000100;
1010:100000001000;
1011:100000000100;
1100:100000000001;
1101:100000000001;
1110:100000000000;
1111:000000000110;
10000:100000000011;
10001:100000000101;
10010:000000000000;
10011:100000000100;
10100:100000000011;
10101:000000000001;
10110:100000000000;
10111:000000000001;
11000:100000000100;
11001:000000000100;
11010:000000000000;
11011:000000000101;
11100:000000000101;
11101:000000000010;
11110:000000000011;
11111:100000000011;
100000:100000000010;
100001:000000000001;
100010:000000000001;
100011:000000000100;
100100:100000000000;
100101:000000000100;
100110:100000000000;
100111:100000000010;
101000:000000001000;
101001:000000000110;
101010:000000000000;
101011:100000000010;
101100:100000000101;
101101:100000000100;
101110:100000000011;
101111:100000001010;
110000:100000000000;
110001:100000000010;
110010:000000000111;
110011:100000000011;
110100:000000000001;
110101:100000000011;
110110:100000000100;
110111:000000000110;
111000:100000000000;
111001:100000000001;
111010:000000000100;
111011:000000000011;
111100:000000001010;
111101:100000001011;
111110:100000000000;
111111:000000000010;
1000000:000000000000;
1000001:000000000010;
1000010:000000000001;
1000011:000000000100;
1000100:100000000100;
1000101:100000000111;
1000110:000000000100;
1000111:100000000010;
1001000:000000000001;
1001001:100000000000;
1001010:000000000010;
1001011:100000000001;
1001100:100000001010;
1001101:000000000110;
1001110:100000000100;
1001111:000000000100;
1010000:100000000001;
1010001:000000000000;
1010010:000000000000;
1010011:000000000100;
1010100:000000000100;
1010101:100000000001;
1010110:100000000100;
1010111:000000000100;
1011000:100000000110;
1011001:000000000010;
1011010:000000000010;
1011011:000000000100;
1011100:000000001000;
1011101:100000000101;
1011110:100000000000;
1011111:000000000000;
1100000:000000000000;
1100001:100000000110;
1100010:100000000111;
1100011:100000000001;
1100100:100000000000;
1100101:100000000001;
1100110:100000001000;
1100111:000000000010;
1101000:000000000010;
1101001:000000000011;
1101010:100000000010;
1101011:000000000010;
1101100:100000000110;
1101101:100000000000;
1101110:000000000000;
1101111:000000000001;
1110000:000000000011;
1110001:100000000011;
1110010:100000000011;
1110011:100000000101;
1110100:000000001011;
1110101:100000000000;
1110110:100000000001;
1110111:000000000001;
1111000:000000000001;
1111001:100000000000;
1111010:100000000001;
1111011:000000001000;
1111100:000000000000;
1111101:100000000001;
1111110:100000000110;
1111111:100000000100;
10000000:000000000101;
10000001:000000000100;
10000010:000000000101;
10000011:100000000011;
10000100:100000000101;
10000101:000000000001;
10000110:000000000101;
10000111:000000000001;
10001000:000000000001;
10001001:000000000111;
10001010:100000000000;
10001011:100000000100;
10001100:100000001000;
10001101:000000000010;
10001110:100000000010;
10001111:100000000000;
10010000:000000000101;
10010001:000000000011;
10010010:100000000001;
10010011:000000000110;
10010100:000000000110;
10010101:100000000010;
10010110:100000000000;
10010111:000000000000;
10011000:100000000000;
10011001:100000000100;
10011010:000000000100;
10011011:000000000111;
10011100:000000000001;
10011101:100000000010;
10011110:100000000110;
10011111:100000000100;
END
Here's my simulation result
I don't know why out remains '000'. And how should I use the ROM block?
Most likely is that your initialization fails. Check for an error message in your simulation log file like 'Can't open...'.
The reason why I suspect that is because the Xilinx file locations in Vivado are very, very nasty. They are relative to the simulation directory which can be 4 or 5 directories deep inside the Vivado project directory. Not only that, the depth recently changed when I switched to a newer version and I had to adapt every path in every old test-bench! (Thank you Xilinx!!)
This is an example of a simulation where I had to pass a filename in my testbench (tb):
.file_path ("../../../../../test_data/"),
.file_name ("testpattern_00.bin"),
The directory structure I use is:
---+--tb
| |
| +-- test_bench.sv
|
+--test_data
| |
| +-- testpattern_00.bin
|
+--vivado_directory
|
+--vivado_project.xpr

How to do a non-blocking read on a non-socket fd

Is there a way to do a single read() in non-blocking mode on a pipe/terminal/etc, the way I can do it on a socket with recv(MSG_DONTWAIT)?
The reason I need that is because I cannot find any guarantee that a read() on a file-descriptor returned as ready for reading by select() or poll() will not block.
I know can make the file descriptor non-blocking with fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) but this will change the mode on that file descriptor globally, not just in the calling thread/process. For example:
% perl -MFcntl=F_SETFL,F_GETFL,O_NONBLOCK -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) | O_NONBLOCK; select undef, undef, undef, undef'
^Z # put it in the background
% cat
cat: -: Resource temporarily unavailable
This will also make the fd non blocking for both reading and writing, which may confuse the hell out of another process doing the opposite on the same fd, as in:
non_blocking_read | filter | blocking_write
One way I think of is to save the file status flags on starting up and SIGCONT, and restore them on exiting and on SIGTSTP (just the way it's done with the termios settings), but this is very limited, race-prone, and will leave a mess behind in the case where the program exited abnormally.
Putting a save/restore with fcntl() before/after each read() also feels ugly and dumb, and may have other issues too. The same with an ioctl(FIONREAD) just before the read (which I'm not even sure it will work reliably with any fd; assurances in that direction will be welcome, though).
I would be happy even with system specific (eg. linux or bsd-only) solutions.
For reference, here is a discussion about fixing it in linux; the idea didn't seem to get anywhere, though.
A Linux only solution would be to reopen the file descriptor via
"/dev/stdin"|"/dev/tty"|"/dev/fd/$fd".
C example:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd;
char buf[8];
int flags;
if(0>(fd=open("/dev/stdin", O_RDONLY))) return 1;
if(0>(flags = fcntl(fd,F_GETFL))) return 1;
if(0>(flags = fcntl(fd,F_SETFL,flags|O_NONBLOCK))) return 1;
sleep(3);
puts("reading");
ssize_t nr = read(fd, buf, sizeof(buf));
printf("read=%zd\n", nr);
return 0;
}
Unlike a duplicated file descriptor, a reopened filedescriptor will have independent file status flags.

64-bit ELF yielding unexplainable results

Can someone explain why the following code yields different results on the second printf if I comment the first printf line or not, in 64 bits?
/* gcc -O0 -o test test.c */
#include <stdio.h>
#include <stdlib.h>
int main() {
char a[20] = {0};
char b = 'a';
int count=-1;
// printf("%.16llx %.16llx\n", a, &b);
printf("%x\n", *(a+count));
return 0;
}
I get the following results for the second printf:
commented: 0
uncommented: 61
Thanks in advance!
iansus
Can someone explain why the following code yields different results on the second printf if I comment the first printf line or not
Your program uses a[-1], and thus exhibits undefined behavior. Anything can happen, and figuring out exactly why one or the other thing happenes is pointless.
The precise reason is that you are reading memory that gets written to by the first printf (when commented in).
I get a different result (which is expected with undefined behavior):
// with first `printf` commented out:
ffffffff
// with it commented in:
00007fffffffdd20 00007fffffffdd1b
ffffffff
You could see where that memory is written to by setting a GDB watchpoint on it:
(gdb) p a[-1]
$1 = 0 '\000'
(gdb) p &a[-1]
$2 = 0x7fffffffdd1f ""
(gdb) watch *(int*)0x7fffffffdd1f
Hardware watchpoint 4: *(int*)0x7fffffffdd1f
(gdb) c
Continuing.
Hardware watchpoint 4: *(int*)0x7fffffffdd1f
Old value = 0
New value = 255
main () at t.c:12
12 printf("%.16llx %.16llx\n", a, &b);
It my case above, the value is written as part of initializing count=-1. That is, with my version of gcc, count is located just before a[0]. But this may depend on compiler version, exactly how this compiler was built, etc. etc.

Allocating memory in Flash for user data (STM32F4 HAL)

I'm trying to use the internal flash of an STM32F405 to store a bunch of user settable bytes that remain after rebooting.
I'm using:
uint8_t userConfig[64] __attribute__((at(0x0800C000)));
to allocate memory for the data I want to store.
When the program starts, I check to see if the first byte is set to 0x42, if not, i set it using:
HAL_FLASH_Unlock();
HAL_FLASH_Program(TYPEPROGRAM_BYTE, &userConfig[0], 0x42);
HAL_FLASH_Lock();
After that I check the value in userConfig[0] and I see 0x42... Great!
When I hit reset, however, and look at the location again, it's not 0x42 anymore...
Any idea where I'm going wrong? I've also tried:
#pragma location = 0x0800C00
volatile const uint8_t userConfig[64]
but I get the same result..
Okay I found an answer on the ST forums thanks to clive1. This example works for an STM32F405xG.
First we need to modify the memory layout in the linker script file (.ld file)
Modify the existing FLASH and add a new line for DATA. Here I've allocated all of section 11.
MEMORY
{
FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 1M-128K
DATA (RWX) : ORIGIN = 0x080E0000, LENGTH = 128k
...
...
}
Manual for editing linker files on the sourceware website
In the same file, we need to add:
.user_data :
{
. = ALIGN(4);
*(.user_data)
. = ALIGN(4);
} > DATA
This creates a section called .user_data that we can address in the program code.
Finally, in your .c file add:
__attribute__((__section__(".user_data"))) const uint8_t userConfig[64]
This specifies that we wish to store the userConfig variable in the .user_data section and const makes sure the address of userConfig is kept static.
Now, to write to this area of flash during runtime, you can use the stm32f4 stdlib or HAL flash driver.
Before you can write to the flash, it has to be erased (all bytes set to 0xFF) The instructions for the HAL library say nothing about doing this for some reason...
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );
FLASH_Erase_Sector(FLASH_SECTOR_11, VOLTAGE_RANGE_3);
HAL_FLASH_Program(TYPEPROGRAM_WORD, &userConfig[index], someData);
HAL_FLASH_Lock();

Unix If file exists, rename

I am working on a UNIX task where i want check if a particular log file is present in the directory or not. If it is present, i would like to rename it by appending a timestamp at the end. The format of the file name is as such: ServiceFileName_0.log
This is what i have so far but it wouldn't rename when i run the script, even though there is a file with the name ServiceFileName_0.log present.
renameLogs()
{
#If a ServiceFileName log exists, rename it
if [ -f $MY_DIR/logs/ServiceFileName_0.log ];
then
mv ServiceFileName_0.log ServiceFileName_0.log.%M%H%S
fi
}
Pls Help!
Thanks
renameLogs()
{
if [ -f $MY_DIR/logs/ServiceFileName_0.log ]
then mv $MY_DIR/ServiceFileName_0.log $MY_DIR/ServiceFileName_0.log.$(date +%M%H%S)
fi
}
Use the directory prefix consistently. Also you need to specify the time properly, as shown.
Better, though (less repetition):
renameLogs()
{
logfile="$MY_DIR/logs/ServiceFileName_0.log"
if [ -f "$logfile" ]
then mv "$logfile" "$logfile.$(date +%H%M%S)"
fi
}
NB: I've reordered the format from MMHHSS to the more conventional HHMMSS order. If you work with date components too, you should seriously consider using the ordering recommended by ISO 8601, which is [YYYY]mmdd. It groups all the log files for a month together in an ls listing, which is usually helpful. Using ddmm order means that the files for the first of each month are grouped together, then the files for the second of each month, etc. This is usually less desirable.
You might need to prefix the file name with the $MY_DIR path, just like you did in the test.
You could replace this:
mv ServiceFileName_0.log ServiceFileName_0.log.%M%H%S
with this
mv $MY_DIR/logs/ServiceFileName_0.log $MY_DIR/logs/ServiceFileName_0.log.%M%H%S
This isn't your apparent immediate problem, but the if construct is wrong: it introduces a time-of-check to time-of-use race condition. In between the if [ -f check and the mv, some other process could come along and change things so you can't move the file anymore even though the check succeeded.
To avoid this class of bugs, always write code that starts by attempting the operation you want to do, then if it failed, figure out why. In this case, what you want is to do nothing if the source file didn't exist, but report an error if the operation failed for any other reason. There is no good way to do that in portable shell, you need something that lets you inspect errno. I'd probably write this C helper:
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv)
{
if (argc != 3) {
fprintf(stderr, "usage: %s source destination\n", argv[0]);
return 2;
}
if (rename(argv[1], argv[2]) && errno != ENOENT) {
fprintf(stderr, "rename '%s' to '%s': %s\n",
argv[1], argv[2], strerror(errno));
return 1;
}
return 0;
}
and then use it like so:
renameLogs()
{
( cd "$MY_DIR/logs"
rename_if_exists ServiceFileName_0.log ServiceFileName_0.log.$(date +%M%H%S)
)
}
The ( cd construct fixes your immediate problem, and unlike the other suggestions, avoids another race in which some other process comes along and messes with the logs directory or its parent directories.
Obligatory shell scripting addendum: Always enclose variable expansions in double quotes, except in the rare cases where you want the expansion to be subject to word splitting.

Resources