Close

Ubiquitous libc

A project log for Yet Another Simple Compiler

Rebuilt Tarvo Korrovits' Acts Language compiler.

agpcooperagp.cooper 03/17/2019 at 02:202 Comments

Libc Functions

As I parse the "self compiling" compiler I see just how ubiquitous "libc" is.

But I think I the "atomic" functions are:

  1. fgetc()
  2. fputc()
  3. feof()
  4. malloc()
  5. free()

Actually I only need a memory pointer to the "heap" for malloc() and free().

"feof()" makes the list as I need to know when input (serial) data is available.

I have actually coded in ActsL most of the functions I need:

Still more to code.

The ubiquitous fprintf()

"fprintf()" is a complex and large procedure for a simple compiler.

As the arguments are variable, the count needs to be given to the function in some manner. Perhaps a global variable for the argument count or a NULL delimiter on the stack.

Better to use fputs() and construct a string using strcpy(), strcat() and itoa().

Looking Forward

I was contemplating my TTA8 as a target (when I get it working!).

The memory page size is limited to 64 bytes but I have up to 255 pages. So it is doable.

I now have the "p code" (i.e CodeGen.h) specification for the CPU interpreter the emulate.

AlanX

Discussions

agp.cooper wrote 03/17/2019 at 09:13 point

Okay, it will be a roll your own "bytes_available()" or "keyhit()". Not hard.

This compiler has an "args" counter that is valid up until the call returns (during compile only). Easy enough to save this counter to a run time variable before the call.

And another option is to count the required arguments from the format string.

Its not that I am frightened of writing (copying!) fprintf() its just that the code is nearly as big as the compiler itself and it is overkill for such a simple compiler.

Still if I think about how I am going to use my Home Brew CPU then all I really need is a cross-compiler and a simple interpreter like "Mouse", "BASIC" or "Forth". In this case why care about "self compile" or fprintf()?

(Mouse is a char token based RPN interpreter.)

AlanX

  Are you sure? yes | no

Ken Yap wrote 03/17/2019 at 04:55 point

>feof()" makes the list as I need to know when input (serial) data is available.

feof() doesn't tell you when data is available, rather it tells you when the end of stream has been encountered. Traditionally all C library I/O functions were blocking and non-blocking was achieved by other non-standardised means. In later versions of Unix, functions like poll() and select() appeared.

You might as well define your own non-blocking byte reading function, or a polling function, say bytes_avail(), rather than redefining feof() to be something it is not.

>"fprintf()" is a complex and large procedure for a simple compiler.

fprintf() is an example of a variadic function. Traditionally this has been handled in compilers by generating code to push the arguments onto the stack starting from the last so the address of the first argument is known. Unfortunately it is also an unsafe function in that there could be more format specifiers than actual arguments. Modern compilers actually try to detect that and warn you if you write something like:

fprintf(stderr, "The value of %x is %d\n", loc);  // forgot the value corresponding to %d

  Are you sure? yes | no