I'm using the bounded version of the Multiway Tree. I can create my element type and instantiate a tree of my type but how do I create the root? I see several forms of Insert_Child. All my attempts at using Insert_Child fail because I use No_Element for the Parent or Before argument.
Does anyone have an example of using the multiway tree package they can point me to?
I'm using the free Gnat version of Ada if it matters.
Create a variable of type Tree; there's a hint in the ARM,
There is a special node, the root, which is always present and has
neither an associated element value nor any parent node. The root node
provides a place to add nodes to an otherwise empty tree and
represents the base of the tree.
Something like
with Ada.Containers.Multiway_Trees;
with Ada.Text_IO; use Ada.Text_IO;
procedure Mway is
package Trees is new Ada.Containers.Multiway_Trees (Integer);
T : Trees.Tree;
C : Trees.Cursor;
begin
C := T.Root;
T.Append_Child (Parent => C, New_Item => 1);
T.Append_Child (Parent => C, New_Item => 2);
for E of T loop
Put_Line (E'Img);
end loop;
end Mway;
the output of which is
1
2
Thank you for the answer but your description of the root not having an element may cause me to change my design. I anticipated building a tree of components made of subcomponents and so forth. I wanted to roll up the property, say mass or price, of each element into the total for the assembly and store it in the root.
I guess I can have the first node I create be the placeholder for the assembly total, then have the real tree branch off of that. Seems clumsy but workable.
/s/ Bob
Interestingly, when I try the example code I get a STORAGE_ERROR at the tree iterator loop.
I'm running Debian under the Windows Subsystem for Linux. WSL1 does not allow you to adjust the stack size via ulimit.
The fix appears to be to turn on the compiler optimisation:
ebolar#Beowulf:~/Build/Ada/src$ gnatmake -s -g simpletree
gcc-6 -c -g simpletree.adb
simpletree.adb:3:11: warning: file name does not match unit name, should be "mway.adb"
gnatbind-6 -x simpletree.ali
gnatlink-6 simpletree.ali -g
ebolar#Beowulf:~/Build/Ada/src$ ./simpletree
Load up the tree
Check out the contents
raised STORAGE_ERROR : stack overflow or erroneous memory access
ebolar#Beowulf:~/Build/Ada/src$ gnatmake -s -g -O simpletree
gcc-6 -c -g -O simpletree.adb
simpletree.adb:3:11: warning: file name does not match unit name, should be "mway.adb"
gnatbind-6 -x simpletree.ali
gnatlink-6 simpletree.ali -g -O
ebolar#Beowulf:~/Build/Ada/src$ ./simpletree
Load up the tree
Check out the contents
1
2
Related
I have got a 16-bit MPU which is different from x86_16 in size of size_t, ptrdiff_t etc. Can anybody give me details and clear instructions about how to customize machine dependency in Frama-C for my MPU?
There is currently no way to do that directly from the command line: you have to write a small OCaml script that will essentially define a new Cil_types.mach (a record containing the necessary information about your architecture) and register it through File.new_machdep. Assuming you have a file my_machdep.ml looking like that:
let my_machdep = {
Cil_types.sizeof_short = 2;
sizeof_int = 2;
sizeof_long = 4;
(* ... See `cil_types.mli` for the complete list of fields to define *)
}
let () = File.new_machdep "my_machdep" my_machdep
You will then be able to launch Frama-C that way to use the new machdep:
frama-c -load-script my_machdep.ml -machdep my_machdep [normal options]
If you want to have the new machdep permanently available, you can make it a Frama-C plugin. For that, you need a Makefile of the following form:
FRAMAC_SHARE:=$(shell frama-c -print-share-path)
PLUGIN_NAME=Custom_machdep
PLUGIN_CMO=my_machdep
include $(FRAMAC_SHARE)/Makefile.dynamic
my_machdep must be the name of your .ml file. Be sure to choose a different name for PLUGIN_NAME. Then, create an empty Custom_machdep.mli file (touch Custom_machdep.mli should do the trick). Afterwards, make && make install should compile and install the plug-in so that it will be automatically loaded by Frama-C. You can verify this by launching frama-c -machdep help that should output my_machdep among the list of known machdeps.
UPDATE
If you are using some headers from Frama-C's standard library, you will also have to update $(frama-c -print-share-path)/libc/__fc_machdep.h in order to define appropriate macros (related to limits.h and stdint.h mostly).
I have a C++ library and it has a few of C++ static objects. The library could suffer from C++ static initialization fiasco. I'm trying to vet unforeseen translation unit dependencies by randomizing the order of the *.o files during a build.
I visited 2.3 How make Processes a Makefile in the GNU manual and it tells me:
Goals are the targets that make strives ultimately to update. You can override this behavior using the command line (see Arguments to Specify the Goals) ...
I also followed to 9.2 Arguments to Specify the Goals, but a treatment was not provided. It did not surprise me.
Is it possible to have Make randomize its goals? If so, then how do I do it?
If not, are there any alternatives? This is in a test environment, so I have more tools available to me than just GNUmake.
Thanks in advance.
This is really implementation-defined, but GNU Make will process targets from left to right.
Say you have an OBJS variable with the objects you want to randomize, you could write something like (using e.g. shuf):
RAND_OBJS := $(shell shuf -e -- $(OBJS))
random_build: $(RAND_OBJS)
This holds as long as you're not using parallel make (-j option). If you are the order will still be randomized, but it will also depend on number of jobs, system load, current phase of the moon, etc.
Next release of GNU make will have --shuffle mode. It will allow you to execute prerequisites in random order to shake out missing dependencies by running $ make --shuffle.
The feature was recently added in https://savannah.gnu.org/bugs/index.php?62100 and so far is available only in GNU make's git tree.
I used
readelf --dyn-sym my_elf_binary | grep FUNC | grep UND
to display the dynamically imported functions of my_elf_binary, from the dynamic symbol table in the .dynsym section to be precise. Example output would be:
[...]
3: 00000000 0 FUNC GLOBAL DEFAULT UND tcsetattr#GLIBC_2.0 (3)
4: 00000000 0 FUNC GLOBAL DEFAULT UND fileno#GLIBC_2.0 (3)
5: 00000000 0 FUNC GLOBAL DEFAULT UND isatty#GLIBC_2.0 (3)
6: 00000000 0 FUNC GLOBAL DEFAULT UND access#GLIBC_2.0 (3)
7: 00000000 0 FUNC GLOBAL DEFAULT UND open64#GLIBC_2.2 (4)
[...]
Is it safe to assume that the names associated to these symbols, e.g. the tcsetattr or access, are always unique? Or is it possible, or reasonable*), to have a dynamic symbol table (filtered for FUNC and UND) which contains two entries with the same associated string?
The reason I am asking is that I am looking for a unique identifier for dynamically imported functions ...
*) Wouldn't the dynamic linker resolve all "UND FUNC symbols" with the same name to the same function anyway?
Yes, given a symbol name and the set of libraries an executable is linked against, you can uniquely identify the function. This behavior is required for linking and dynamic linking to work.
An illustrative example
Consider the following two files:
librarytest1.c:
#include <stdio.h>
int testfunction(void)
{
printf("version 1");
return 0;
}
and librarytest2.c:
#include <stdio.h>
int testfunction(void)
{
printf("version 2");
return 0;
}
Both compiled into shared libraries:
% gcc -fPIC -shared -Wl,-soname,liblibrarytest.so.1 -o liblibrarytest.so.1.0.0 librarytest1.c -lc
% gcc -fPIC -shared -Wl,-soname,liblibrarytest.so.2 -o liblibrarytest.so.2.0.0 librarytest2.c -lc
Note that we cannot put both functions by the same name into a single shared library:
% gcc -fPIC -shared -Wl,-soname,liblibrarytest.so.0 -o liblibrarytest.so.0.0.0 librarytest1.c librarytest2.c -lc
/tmp/cctbsBxm.o: In function `testfunction':
librarytest2.c:(.text+0x0): multiple definition of `testfunction'
/tmp/ccQoaDxD.o:librarytest1.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
This shows that symbol names are unique within a shared library, but do not have to be among a set of shared libraries.
% readelf --dyn-syms liblibrarytest.so.1.0.0 | grep testfunction
12: 00000000000006d0 28 FUNC GLOBAL DEFAULT 10 testfunction
% readelf --dyn-syms liblibrarytest.so.2.0.0 | grep testfunction
12: 00000000000006d0 28 FUNC GLOBAL DEFAULT 10 testfunction
Now lets link our shared libraries with an executable. Consider linktest.c:
int testfunction(void);
int main()
{
testfunction();
return 0;
}
We can compile and link this against either shared library:
% gcc -o linktest1 liblibrarytest.so.1.0.0 linktest.c
% gcc -o linktest2 liblibrarytest.so.2.0.0 linktest.c
And run each of them (note I'm setting the dynamic library path so the dynamic linker can find the libraries, which are not in a standard library path):
% LD_LIBRARY_PATH=. ./linktest1
version 1%
% LD_LIBRARY_PATH=. ./linktest2
version 2%
Now lets link our executable to both libraries. Each is exporting the same symbol testfunction and each library has a different implementation of that function.
% gcc -o linktest0-1 liblibrarytest.so.1.0.0 liblibrarytest.so.2.0.0 linktest.c
% gcc -o linktest0-2 liblibrarytest.so.2.0.0 liblibrarytest.so.1.0.0 linktest.c
The only difference is the order the libraries are referenced to the compiler.
% LD_LIBRARY_PATH=. ./linktest0-1
version 1%
% LD_LIBRARY_PATH=. ./linktest0-2
version 2%
Here are the corresponding ldd output:
% LD_LIBRARY_PATH=. ldd ./linktest0-1
linux-vdso.so.1 (0x00007ffe193de000)
liblibrarytest.so.1 => ./liblibrarytest.so.1 (0x00002b8bc4b0c000)
liblibrarytest.so.2 => ./liblibrarytest.so.2 (0x00002b8bc4d0e000)
libc.so.6 => /lib64/libc.so.6 (0x00002b8bc4f10000)
/lib64/ld-linux-x86-64.so.2 (0x00002b8bc48e8000)
% LD_LIBRARY_PATH=. ldd ./linktest0-2
linux-vdso.so.1 (0x00007ffc65df0000)
liblibrarytest.so.2 => ./liblibrarytest.so.2 (0x00002b46055c8000)
liblibrarytest.so.1 => ./liblibrarytest.so.1 (0x00002b46057ca000)
libc.so.6 => /lib64/libc.so.6 (0x00002b46059cc000)
/lib64/ld-linux-x86-64.so.2 (0x00002b46053a4000)
Here we can see that while symbols are not unique, the way the linker resolves them is defined (it appears that it always resolves the first symbol it encounters). Note that this is a bit of a pathological case as you normally wouldn't do this. In the cases where you would go this direction there are better ways of handling symbol naming so they would be unique when exported (symbol versioning, etc)
In summary, yes, you can uniquely identify the function given its name. If there happens to be multiple symbols by that name, you identify the proper one using the order the libraries are resolved in (from ldd or objdump, etc). Yes, in this case you need a bit more information that just its name, but it is possible if you have the executable to inspect.
Note that in your case, the name of the first function import is not just tcsetattr but tcsetattr#GLIBC_2.0. The # is how the readelf program displays a versioned symbol import.
GLIBC_2.0 is a version tag that glibc uses to stay binary compatible with old binaries in the (unusual but possible) case that the binary interface to one of its functions needs to change. The original .o file produced by the compiler will just import tcsetattr with no version information but during static linking, the linker has noticed that the actual symbol exported by lic.so carries a GLIBC_2.0 tag, and so it creates a binary that insists on importing the particular tcsetattr symbol that has version GLIBC_2.0.
In the future there might be a libc.so that exports one tcsetattr#GLIBC_2.0 and a different tcsetattr#GLIBC_2.42, and the version tag will then be used to find which one a partcular ELF object refers to.
It is possible that the same process may also use tcsetattr#GLIBC_2.42 at the same time, such as if it uses another dynamic library which was linked against a libc.so new enough to provide it. The version tags ensure that both the old binary and the new library get the function they expect from the C library.
Most libraries don't use this mechanism and instead just rename the entire library if they need to make breaking changes to their binary interfaces. For example, if you dump /usr/bin/pngtopnm you'll find that the symbols it imports from libnetpbm and libpng are not versioned. (Or at least that's what I see on my machine).
The cost of this is that you can't have a binary that links against one version of libpng and also links against another library that itself links against a different libpng version; the exported names from the two libpng's would clash.
In most cases this is manageable enough through careful packaging practice that maintaining the library source to produce useful version tags and stay backwards compatible is not worth the trouble.
But in the particular case of the C library and a few other vital system libraries, changing the name of the library would be so extremely painful that it makes sense for the maintainers to jump through some hoops in order to ensure it will never need to happen again.
Although in most cases every symbol is unique, there are a handful of exceptions. My favorite is multiple identical symbol import used by PAM (pluggable authentication modules) and NSS (Name Service Switch). In both cases all modules written for either interface use a standard interface with standard names. A common and frequently used example is what happens when you call get host by name. The nss library will call the same function in multiple libraries to get an answer. A common configuration calles the same function in three libraries! I have seen the same function called in five different libraries from one function call, and that was not the limit just what was useful. There is special calls to the dynamic linker need to do this and I have not familiarised myself with the mechanics of doing this, but there is nothing special about the linking of the library module that is so loaded.
I have an ada program that has a main procedure, now I want to add another procedure but I got an error saying "end of file expected, file can have only one compilation unit". I did some looking an I think it is because you can only have 1 procedure per file. Do I have to create another file and put the procedure alone in that? If so how would I compile both the codes and run it? Can someone show me how I would be able to compile both and run the whole file together.
As the compiler says, you can only have one compilation unit per file. A main program is compilation unit, which is a procedure.
If you want one program to run two procedures which both are compilation units, when you can do it like this:
with One_Procedure,
Another_Procedure;
procedure Sequential is
begin
One_Procedure;
Another_Procedure;
end Sequential;
If you want to run the two procedures in parallel do it like this:
with One_Procedure,
Another_Procedure;
procedure Parallel is
task One;
task Another;
task body One is
begin
One_Procedure;
end One;
task body Another is
begin
Another_Procedure;
end Another;
begin
null;
end Parallel;
The procedures may of course also be declared in the declarative region of the main program or in some packages.
Both recent GNATs and GPRbuild have options for indicating which units of a file you want compiled: that's -gnateINNN for gcc, and -eInn for gprbuild, as documented here.
Another option is to become familiar with gnatchop for extracting compilation units from files, and with -m for minimal recompilation; the latter prevents having to compile the world only because of running gnatchop when an edit has not "semantically" touched all compilation units in a file. GNAT then ignores time stamps. I sometimes run commands like
gnatchop -r -w -c allofit.ada && gnatmake -Ptest -m someunit.adb
where someunit.adb is generated for compilation unit Someunit (a procedure, a package) contained in file allofit.ada.
You can have 1 main procedure but several procedures within main procedure.
procedure main is
...text...
procedure sub1 () is
begin
...text...
end sub1;
procedure sub2 () is
begin
...text...
end sub2;
...text...
end main;
I'm using the excellent UNIX 'comm' command line utility in an application which I developed on a BSD platform (OSX). When I deployed to my Linux production server I found out that sadly, Ubuntu Linux's 'comm' utility does not take the -i flag to indicate that the lines should be compared case-insensitive. Apparently the POSIX standard does not require the -i option.
So... I'm in a bind. I really need the -i option that works so well on BSD. I've gone so far to try to compile the BSD comm.c source code on the Linux box but I got:
http://svn.freebsd.org/viewvc/base/user/luigi/ipfw3-head/usr.bin/comm/comm.c?view=markup&pathrev=200559
me#host:~$ gcc comm.c
comm.c: In function ‘getline’:
comm.c:195: warning: assignment makes pointer from integer without a cast
comm.c: In function ‘wcsicoll’:
comm.c:264: warning: assignment makes pointer from integer without a cast
comm.c:270: warning: assignment makes pointer from integer without a cast
/tmp/ccrvPbfz.o: In function `getline':
comm.c:(.text+0x421): undefined reference to `reallocf'
/tmp/ccrvPbfz.o: In function `wcsicoll':
comm.c:(.text+0x691): undefined reference to `reallocf'
comm.c:(.text+0x6ef): undefined reference to `reallocf'
collect2: ld returned 1 exit status
Does anyone have any suggestions as to how to get a version of comm on Linux that supports 'comm -i'?
Thanks!
You can add the following in comm.c:
void *reallocf(void *ptr, size_t size)
{
void *ret = realloc(ptr, size);
if (ret == NULL) {
free(ptr);
}
return ret;
}
You should be able to compile it then. Make sure comm.c has #include <stdlib.h> in it (it probably does that already).
The reason your compilation fails is because BSD comm.c uses reallocf() which is not a standard C function. But it is easy to write.
#OP ,there's no need to go to such length as to do your own src code compilation . Here's an alternative suggestion. Since you want case insensitive, you can just convert the cases in both files to lower (or upper case) using another tool such as tr before you pass the files to comm.
tr '[A-Z]' '[a-z]' <file1 > temp1
tr '[A-Z]' '[a-z]' <file2 > temp2
comm temp1 temp2
You could try to cat both files and pipe them to uniq -c -i. It'll show all lines in both files, with the number of appearances in the first column. As long as the original files don't have repeated lines, all lines with the first column >1 are lines common to both files.
Hope it helps!
Does anyone have any suggestions as to how to get a version of comm on Linux that supports 'comm -i'?
Not quite that; but have you checked if your requirements could be satisfied by the join utility? This one does have the -i option on Linux...