User errors versus compiler bugs in Acorm C//C++
tymaja (278) 172 posts |
I set up the latest DDE, and have compiled a RISC OS ROM – showing that it works (and works between reboots etc); Using a fresh reboot to avoid clashes with the ROM build system, I am writing a small test app in C. The lack of an 0b0101011 or a 2-11010101 operator for binary is annoying (I guess we have to use hex instead for binary); I have come across an issue: I am using h and c folders, no subdirectories (need to learn how to make those work!): I have, in the c folder, main.c I have, in the h folder, hello.h main.c #includes hello.h and world.h hello.c does printf(“hello”); and returns on compilation, I get a warning “extern ‘world’ not declared in header’. The application still compiles and runs. hello.c and hello.h, and world.c and world.h, are identical (except hello and world are used in function names, and printf); hello.h and world.h are #included in main. As an experiment, Fixes the issue. This is interesting, as it is a copy and paste, meaning typos aren’t responsible. I will probably spend all day chasing down this issue. What I glean so far is that : It feel weird making header files, including those header files, but also, having to manually copy the header file contents after you include it, and redefine + extern all the functions again. Has anyone come across an issue like this? |
tymaja (278) 172 posts |
Figured it out – it was just a difference between Acorn C and gcc; you need to declare functions before defining them! It makes sense – the solution is just to do void function1(uint32_t); This prevents the warning message from occurring |
Chris Mahoney (1684) 2165 posts |
I think you’ve still done something wrong, because you shouldn’t need to declare like that. I’m not at my Risc OS machine at the moment so can’t knock up an example right now though. Edit: Which I then completely forgot about :) |
Rick Murray (539) 13806 posts |
It’s a warning from the compiler. You have the (IIRC) ‘h’ flag defined in the options given to the compiler (like If a function is only to be used within a specific bit of code and not have global scope, it should be declared as static void function1(uint32_t variable) and if it is a globally visible function, then yes, it should be defined (as I’m surprised gcc doesn’t warn about this sort of thing (unless, like the DDE, it’s an option you can choose). This applies to variable definitions as well. Refer to https://leimao.github.io/blog/Static-Extern-C/ for more details (and tell me if you think it was written by AI). |
Rick Murray (539) 13806 posts |
Though it is worth clarifying that with variables, 1, if a variable is being declared at module level (outside of a function), then it means that the variable only has scope within that module, that is to say is is non-existent elsewhere in the program. Something declared static in hello.c cannot be seen or used in world.c. 2, if a variable is declared as static within a function, this instructs the compiler to place the variable in the static storage area and not on the stack. Which effectively means the value is retained across function calls. This gives it the benefit of persistence available to globals or module level variables without being global or module-visible. Also if you initialise it to a specific value, like zero, that will only happen the very first time. From that point onwards the value on function entry will be “whatever it was last set to”. |
tymaja (278) 172 posts |
All very useful info – will look into static more too. I realised my issue was not declaring functions before defining them … I was using a DDE on the Pi5 (CodeLite) – it is good, not too intrusive, but I think it ‘patched up’ my not including h files for c files within the c files! I started coding an ARM32 emulator in C (will take a few days as a learning project) before I go back to vdu drivers. I had already started coding ARM BBC BASIC into C! Since I am being a newbie, I may as well ask : In Acorn C, how do we specify binary? 0b01010101 doesn’t work, 2_0101000 doesn’t work, and … How do we specify subfolders? I have ‘c’ and ‘h’ folders, but if I wanted to make a sub folder, how do I do that? h.function1 can be included as function1.h, for example, but I tried subfolders in a few ways, and they aren’t found. The DDE examples don’t use subfolders. I found the C ShellCLI module by Julie in the RO sources, which I am using to learn from, but it didn’t need subfolders either! :) |
David J. Ruck (33) 1629 posts |
This very much sounds like running before you can walk. An ARM32 emulator is potentially a very big project, given the number of different 32 bit cores there are and the large number of instructions which have been introduced. It is much larger than most RISC OS emulators which only emulate one of a small number of old 26 bit cores with far smaller instruction sets. You could use it as a learning project, and you have certain have learned a lot by the time you’d have finished. On the other hand there are number of off the shelf 32 bit ARM emulators which you could use such as qemu, or Unicorn which pyromaniac uses. |
tymaja (278) 172 posts |
I agree it does! However – I would be using it as a learning project to get used to Acorn C / C++; Although unreleased (due to being learning projects), I originally made an ARM emulator that ran ARM BBC BASIC, then later a Risc PC emulator that booted to desktop. Both projects were on RISC OS, and the experience making the user-mode ARM emulator (for BBC BASIC) helped me learn a lot about the ‘core’ ARM32 instruction set. The Risc PC emulator also ran under RISC OS, and booted to desktop (RISC OS 5), but I hadn’t yet understood how the keyboard / mouse worked, so it didn’t do much more than this! Since my last post, I have done some work on an ARM emulator. I will try to find an example of how to specify binary, and how to use subdirectories in Acorn C. I do agree that emulating a modern 32-bit ARM CPU is a major project (the sheer number of instructions!), but it can be done (as an example, a few days ago, I got RISC OS 5 (BCM2835) right up until the point where the MMU switches on, in a few days, all in C!) What I want to do is learn how to use Acorn C, so I can write code that can be modified with minimal effort to compile under gcc as well. Will keep learning! |
Chris Mahoney (1684) 2165 posts |
OK, having sat down and tried it (it’s been quite a while since I’ve done any plain old C!) I think you didn’t #include your .h from its .c. For example, your hello.c probably doesn’t/didn’t This Zip file contains a working example of the project you described in your first post. It should build (via amu) with no warnings. |
tymaja (278) 172 posts |
You are 100% correct – I wan’t including the h file in the c file 🤪 – and because I was just getting started in Acorn C, I didn’t get the issue of ‘calling a functiom further down in the file’ which would have shown me the issue! Either gcc, or the DDE I was using on the Pi5, was correcting mistakes like that, at least in the simple test code I tried there, causing added confusion as it did it without warnings or anything. I also found out the answer to the issue of specifying binary numbers in C … you can’t! (at least, you couldn’t until C14, which is when they added the 0b notation; I looked through the Acorn C/C++ manual in the hope of finding a macro language to define binary numbers, but couldn’t find anything, so; I just made a file, binary.h. It start#: #define b0 0 #define b00 0×0 … and finishes #define b11111111 0xFF so, I can at least use any bit pattern from 0-255, including stuff like b00000001 etc :) |
Jeff Doggett (257) 234 posts |
If you are using #defines to declare a sequence then you might want to consider using an enum. |
Simon Willcocks (1499) 509 posts |
FWIW, I wrote a couple of ARM emulators 15 years ago. You might like to have a look at arm_arm_emulator.c in https://sourceforge.net/p/ro-lf/code/HEAD/tree/ROLF/rolf/Libs/Compatibility/ (there’s also an x386 version in the same directory). It might be a bit dusty, but it won’t have rusted! |
nemo (145) 2529 posts |
tymaja wrote
As it happens, I’ve had b0 to b31 defined in my Aasm headers for decades and use the idiom so often I was considering adding it to nemoBasic – even though it already supports the <base>_<digits> syntax. Why the Acorn tools never gained any of these Acorn idioms (&hex, %bin, base_digits) I don’t know. “Portability” perhaps. Boo. |
David J. Ruck (33) 1629 posts |
Even C99 was long after Acorn. |