Relocate kolibri-libc from GitHub

git-svn-id: svn://kolibrios.org@8622 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Magomed Kostoev (mkostoevr) 2021-03-02 17:58:11 +00:00
parent 95e70a7b8c
commit 1f4d74f500
173 changed files with 10115 additions and 0 deletions

6
contrib/kolibri-libc/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.swp
lib
lib/*
*.o
tests/argtest
source/make.bat

View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,2 @@
# kolibri-libc
Standart C library for KolibriOS

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,24 @@
#!/bin/bash
# Copyright maxcodehack, 2021
# gcc options for build for KolibriOS
# We start w/o param?
if [ -z "$*" ]
then
echo -e "\033[1;31mfatal error: \033[0mno input files"
exit 1
fi
# KLIBC variable exists?
if [ -z "$KLIBC" ]
then
echo -e "\033[1;31mfatal error: \033[0mKLIBC variable not set"
exit 1
fi
# GCC Flags for KolibriOS
FLAGS="-c -m32 -nostdinc -fno-common -fno-builtin -fno-leading-underscore -fno-pie -fno-stack-protector -fno-stack-check -mpreferred-stack-boundary=2"
# And, execute gcc:
gcc $FLAGS -I $KLIBC/source/include $*

View File

@ -0,0 +1,24 @@
#!/bin/bash
# Copyright maxcodehack, 2021
# ld options for build for KolibriOS
# We start w/o param?
if [ -z "$*" ]
then
echo "kld: no input files"
exit 1
fi
# KLIBC variable exists?
if [ -z "$KLIBC" ]
then
echo "kld: KLIBC variable not set"
exit 1
fi
# LD Flags for KolibriOS
FLAGS="-m elf_i386 -nostdlib"
# And, execute ld:
ld $FLAGS -L $KLIBC/bin/lib -T $KLIBC/tests/static.lds $KLIBC/bin/lib/crt0.o $*

View File

@ -0,0 +1,55 @@
AR = ar -rcs
CLINK = ../bin/clink
KPACK = ../bin/kpack
INCLUDE = include
LIB_DIR = ../bin/lib
LIBC.A = $(LIB_DIR)/libc.a
LIBC.OBJ = $(LIB_DIR)/libc.obj
CFLAGS = -I$(INCLUDE) -m32 -nostdinc -nostdlib -DGNUC -Os -fno-common -fno-builtin -fno-leading-underscore -fno-pie
DIRS := string stdlib stdio sys math ctype exports setjmp
cfiles := $(foreach dir,$(DIRS),$(patsubst %.c, %.o, $(wildcard $(dir)/*.c)))
asmfiles := $(foreach dir,$(DIRS),$(patsubst %.s, %.o, $(wildcard $(dir)/*.s)))
.PHONY: clean all
ifdef windir
cfiles := $(subst /,\,$(cfiles))
asmfiles := $(subst /,\,$(asmfiles))
LIB_DIR := $(subst /,\,$(LIB_DIR))
LIBNAME := $(subst /,\,$(LIBNAME))
RM = del /F /Q
MKDIR_P = md
else
RM = rm -rf
MKDIR_P = mkdir -p
endif
all: $(cfiles) $(asmfiles) $(LIB_DIR) $(LIBC.A)
fasm crt/crt0.asm $(LIB_DIR)/crt0.o
$(LIBC.A): $(cfiles) $(asmfiles)
$(AR) $(LIBC.A) $^
$(LIB_DIR):
$(MKDIR_P) $(LIB_DIR)
$(asmfiles):
$(CC) -E -x c -nostdinc -Imath $*.s > $*.sx
$(AS) --32 $*.sx -o $*.o
$(RM) $*.sx
clean:
$(RM) $(cfiles) $(asmfiles)
$(RM) $(LIBNAME)
shared: $(cfiles) $(asmfiles)
$(CLINK) $^
$(KPACK) a.out.obj
mv a.out.obj $(LIBC.OBJ)
test:
make -C ../test -f Makefile.tcc
kex ../test/test

View File

@ -0,0 +1,3 @@
all:
$(MAKE) clean
env CC=kos32-gcc CPP=kos32-cpp AS=kos32-as $(MAKE) shared

View File

@ -0,0 +1,220 @@
format ELF
section '.text' executable
public start
public start as '_start'
;extrn mf_init
extrn main
;include 'debug2.inc'
include 'inc/proc32.inc'
include 'inc/macros.inc'
include 'inc/dll.inc'
__DEBUG__=0
;start_:
virtual at 0
db 'MENUET01' ; 1. Magic number (8 bytes)
dd 0x01 ; 2. Version of executable file
dd start ; 3. Start address
imgsz dd 0x0 ; 4. Size of image
dd 0x100000 ; 5. Size of needed memory
dd 0x100000 ; 6. Pointer to stack
hparams dd 0x0 ; 7. Pointer to program arguments
hpath dd 0x0 ; 8. Pointer to program path
end virtual
start:
;DEBUGF 'Start programm\n'
;init heap of memory
mov eax,68
mov ebx,11
int 0x40
mov [argc], 0
mov eax, [hparams]
test eax, eax
jz .without_path
mov eax, path
cmp word ptr eax, 32fh ; '/#3' UTF8
jne .without_path
mov word ptr eax, 12fh ; '/#1' fix to CP866
.without_path:
mov esi, eax
call push_param
; retrieving parameters
mov esi, params
xor edx, edx ; dl - èä¸ò ïàðàìåòð(1) èëè ðàçäåëèòåëè(0)
; dh - ñèìâîë ñ êîòîðîãî íà÷àëñÿ ïàðàìåòð (1 êàâû÷êè, 0 îñòàëüíîå)
mov ecx, 1 ; cl = 1
; ch = 0 ïðîñòî íîëü
.parse:
lodsb
test al, al
jz .run
test dl, dl
jnz .findendparam
;{åñëè áûë ðàçäåëèòåëü
cmp al, ' '
jz .parse ;çàãðóæåí ïðîáåë, ãðóçèì ñëåäóþùèé ñèìâîë
mov dl, cl ;íà÷èíàåòñÿ ïàðàìåòð
cmp al, '"'
jz @f ;çàãðóæåíû êàâû÷êè
mov dh, ch ;ïàðàìåòð áåç êàâû÷åê
dec esi
call push_param
inc esi
jmp .parse
@@:
mov dh, cl ;ïàðàìåòð â êàâû÷åêàõ
call push_param ;åñëè íå ïðîáåë çíà÷èò íà÷èíàåòñÿ êàêîé òî ïàðàìåòð
jmp .parse ;åñëè áûë ðàçäåëèòåëü}
.findendparam:
test dh, dh
jz @f ; áåç êàâû÷åê
cmp al, '"'
jz .clear
jmp .parse
@@:
cmp al, ' '
jnz .parse
.clear:
lea ebx, [esi - 1]
mov [ebx], ch
mov dl, ch
jmp .parse
.run:
call load_imports
push argv
push [argc]
call main
.exit:
xor eax,eax
dec eax
int 0x40
dd -1
.crash:
jmp .exit
;============================
push_param:
;============================
;parameters
; esi - pointer
;description
; procedure increase argc
; and add pointer to array argv
; procedure changes ebx
mov ebx, [argc]
cmp ebx, max_parameters
jae .dont_add
mov [argv+4*ebx], esi
inc [argc]
.dont_add:
ret
;==============================
;==============================
load_imports:
;==============================
;parameters
; none
;description
; imports must be located at end of image (but before BSS sections)
; the address of end of imports (next byte after imports) is located in imgsz
; look at each import from that address up to illegal import
; legal import is such that:
; first pointer points to procedure name
; and is smaller than imgsz
; second pointer points lo library name, starting with 0x55, 0xAA
; and is smaller than imgsz
; each library should be initialized as appropriate, once
; so as library is initialized, its name will be replaced 0x00
mov ebx, [imgsz] ; byte after imports
.handle_next_import:
sub ebx, 4 ; ebx = pointer to pointer to library name
mov esi, dword[ebx] ; esi = pointer to library name
push ebx
push esi
call load_library ; eax = pointer to library exports
pop esi
pop ebx
test eax, eax
jz .done
sub ebx, 4 ; ebx = pointer to pointer to symbol name
push ebx
stdcall dll.GetProcAddress, eax, dword[ebx]
pop ebx
test eax, eax
jz .fail
mov dword[ebx], eax
jmp .handle_next_import
.done:
ret
.fail:
ret
;==============================
;==============================
load_library:
;==============================
;parameters
; ebx: library name address
;description
; each library should be initialized as appropriate, once
; so as library is initialized, its name will be replaced 0x00
; and 4 next bytes will be set to address of library
; first two bytes of library name must be 0x55, 0xAA (is like a magic)
cld ; move esi further, not back
cmp esi, [imgsz]
ja .fail
lodsb ; al = first byte of library name
cmp al, 0x55
jne .fail
lodsb ; al = second byte of library name
cmp al, 0xAA
jne .fail
lodsb ; al = third byte of library name (0x00 if the library is already loaded)
test al, al
jnz .load
lodsd ; if we here, then third byte is 0x00 => address of library is in next 4 bytes
; now eax contains address of library
ret
.load:
dec esi ; we checked on 0 before, let's go back
mov eax, 68
mov ebx, 19
mov ecx, esi
int 0x40 ; eax = address of exports
mov byte[esi], 0 ; library is loaded, let's place 0 in first byte of name
mov [esi + 1], eax ; now next 4 bytes of library name are replaced by address of library
; call lib_init
stdcall dll.GetProcAddress, eax, lib_init_str ; eax = address of lib_init
test eax, eax
jz .ret
stdcall dll.Init, eax
.ret:
mov eax, [esi + 1] ; put address of library into eax
ret
.fail:
mov eax, 0
ret
;==============================
lib_init_str db 'lib_init', 0
public argc as '__argc'
public params as '__argv'
public path as '__path'
section '.bss'
buf_len = 0x400
max_parameters=0x20
argc rd 1
argv rd max_parameters
path rb buf_len
params rb buf_len
;section '.data'
;include_debug_strings ; ALWAYS present in data section

View File

@ -0,0 +1 @@
__CPU_type fix p5

View File

@ -0,0 +1,158 @@
;-----------------------------------------------------------------------------
; load one or more DLL file in COFF format and try to import functions by our list
; if first function in import list begins with 'lib_', call it as DLL initialization
; return eax = 1 as fail, if anyone of .obj file not found in /sys/lib
; return 0 if all fine, but 0 not garantees in succesfull import - see dll.Link comment
; dirties all registers! eax, ebx, ecx, edx, esi, edi
proc dll.Load, import_table:dword
mov esi, [import_table]
.next_lib:
mov edx, [esi]
or edx, edx
jz .exit
push esi
mov esi, [esi + 4]
mov edi, s_libdir.fname
@@:
lodsb
stosb
or al, al
jnz @b
mcall 68, 19, s_libdir
or eax, eax
jz .fail
stdcall dll.Link, eax, edx
push eax
mov eax, [eax]
cmp dword[eax], 'lib_'
pop eax
jnz @f
stdcall dll.Init, [eax + 4]
@@:
pop esi
add esi, 8
jmp .next_lib
.exit:
xor eax, eax
ret
.fail:
add esp, 4
xor eax, eax
inc eax
ret
endp
;-----------------------------------------------------------------------------
; scans dll export table for a functions we want to import
; break scan on first unresolved import
; no return value
proc dll.Link, exp:dword, imp:dword
push eax
mov esi, [imp]
test esi, esi
jz .done
.next:
lodsd
test eax, eax
jz .done
stdcall dll.GetProcAddress, [exp], eax
or eax, eax
jz @f
mov [esi - 4], eax
jmp .next
@@:
mov dword[esp], 0
.done:
pop eax
ret
endp
;-----------------------------------------------------------------------------
; calls lib_init with predefined parameters
; no return value
proc dll.Init, dllentry:dword
pushad
mov eax, mem.Alloc
mov ebx, mem.Free
mov ecx, mem.ReAlloc
mov edx, dll.Load
stdcall [dllentry]
popad
ret
endp
;-----------------------------------------------------------------------------
; scans export table for a sz_name function
; returns in eax function address or 0 if not found
proc dll.GetProcAddress, exp:dword, sz_name:dword
mov edx, [exp]
xor eax, eax
.next:
or edx, edx
jz .end
cmp dword[edx], 0
jz .end
stdcall strcmp, [edx], [sz_name]
test eax, eax
jz .ok
add edx, 8
jmp .next
.ok:
mov eax, [edx + 4]
.end:
cmp eax, -1
jnz @f
xor eax, eax
@@:
ret
endp
;-----------------------------------------------------------------------------
; compares strings
; returns eax = 0 if equal, -1 otherwise
proc strcmp, str1:dword, str2:dword
push esi edi
mov esi, [str1]
mov edi, [str2]
xor eax, eax
@@:
lodsb
scasb
jne .fail
or al, al
jnz @b
jmp .ok
.fail:
or eax, -1
.ok:
pop edi esi
ret
endp
;-----------------------------------------------------------------------------
if defined dll.Load
s_libdir:
db '/sys/lib/'
.fname rb 32
end if
;-----------------------------------------------------------------------------
proc mem.Alloc, size
push ebx ecx
mov ecx, [size]
mcall 68, 12
pop ecx ebx
ret
endp
;-----------------------------------------------------------------------------
proc mem.ReAlloc, mptr, size
push ebx ecx edx
mov ecx, [size]
mov edx, [mptr]
mcall 68, 20
pop edx ecx ebx
ret
endp
;-----------------------------------------------------------------------------
proc mem.Free, mptr
push ebx ecx
mov ecx,[mptr]
mcall 68, 13
pop ecx ebx
ret
endp
;-----------------------------------------------------------------------------

View File

@ -0,0 +1,597 @@
@^ fix macro comment {
^@ fix }
; --------------------------
macro library [lname,fname]
{
forward
dd __#lname#_library_table__,__#lname#_library_name__
common
dd 0
forward
align 4
__#lname#_library_name__ db fname,0
}
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
if used name
name dd __#name#_import_name__
end if
common
dd 0
forward
if used name
align 4
__#name#_import_name__ db sname,0
end if
}
macro export [name,sname]
{
forward
dd __#name#_export_name__,name
common
dd 0
forward
align 4
__#name#_export_name__ db sname,0
}
; -------------------------
macro m2m dest,src {
push src
pop dest
}
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
endg fix } ; Use endg for ending iglobal and uglobal blocks.
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
uglobal
endg
iglobal
endg
; new application structure
macro meos_app_start
{
use32
org 0x0
db 'MENUET01'
dd 0x01
dd __start
dd __end
dd __memory
dd __stack
if used __params & ~defined __params
dd __params
else
dd 0x0
end if
dd 0x0
}
MEOS_APP_START fix meos_app_start
KOS_APP_START fix meos_app_start
macro code
{
__start:
}
CODE fix code
macro data
{
__data:
IncludeIGlobals
}
DATA fix data
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
IncludeUGlobals
}
UDATA fix udata
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_APP_END fix meos_app_end
KOS_APP_END fix meos_app_end
; macro for defining multiline text data
struc mstr [sstring]
{
forward
local ssize
virtual at 0
db sstring
ssize = $
end virtual
dd ssize
db sstring
common
dd -1
}
; macro for defining multiline text data
struc mls [sstring]
{
forward
local ssize
virtual at 0
db sstring ; mod
ssize = $
end virtual
db ssize
db sstring
common
db -1 ; mod
}
; strings
macro sz name,[data] { ; [mike.dld]
common
if used name
name db data
.size = $-name
end if
}
macro szZ name,[data] { ; same as sz, but for zero terminated string [dunkaist]
common
if used name
name db data,0
.size = $-name-1
end if
}
sz0 fix szZ
macro lsz name,[lng,data] { ; [mike.dld]
common
if used name
label name
forward
if lang eq lng
db data
end if
common
.size = $-name
end if
}
macro szc name,elsz,[data] { ; [mike.dld]
common
local s,m
m = 0
if used name
label name
forward
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
common
.size = $-name
.maxl = m
end if
}
macro lszc name,elsz,[lng,data] { ; [mike.dld]
common
local s,m,c
m = 0
c = 0
if used name
label name
forward
if lang eq lng
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
c = c+1
end if
common
.size = $-name
.maxl = m
.count = c
end if
}
; easy system call macro
macro mpack dest, hsrc, lsrc
{
if (hsrc eqtype 0) & (lsrc eqtype 0)
mov dest, (hsrc) shl 16 + lsrc
else
if (hsrc eqtype 0) & (~lsrc eqtype 0)
mov dest, (hsrc) shl 16
add dest, lsrc
else
mov dest, hsrc
shl dest, 16
add dest, lsrc
end if
end if
}
macro __mov reg,a,b { ; mike.dld
if (~a eq)&(~b eq)
mpack reg,a,b
else if (~a eq)&(b eq)
mov reg,a
end if
}
include 'config.inc'
;__CPU_type equ p5
SYSENTER_VAR equ 0
macro mcall a,b,c,d,e,f,g { ; [mike.dld], [Ghost]
local ..ret_point
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
__mov ebp,g
if __CPU_type eq p5
int 0x40
else
if __CPU_type eq p6
push ebp
mov ebp, esp
push ..ret_point ; it may be 2 or 5 byte
sysenter
..ret_point:
pop edx
pop ecx
else
if __CPU_type eq k6
push ecx
syscall
pop ecx
else
display 'ERROR : unknown CPU type (set to p5)', 10, 13
__CPU_type equ p5
int 0x40
end if
end if
end if
}
; -------------------------
macro __header a,[b] {
common
use32
org 0
db 'MENUET',a
forward
if b eq
dd 0
else
dd b
end if
}
macro __section name {
align 16
label name
}
macro __func name {
if ~used name
display 'FUNC NOT USED: ',`name,13,10
else
align 4
name:
;diff16 `name,0,name
}
macro endf { end if }
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 8
d = '0' + s shr ((8-%) shl 2) and $0F
if d > '9'
d = d + 'A'-'9'-1
end if
display d
end repeat
display 13,10
}
macro diff10 title,l1,l2
{
local s,d,z,m
s = l2-l1
z = 0
m = 1000000000
display title,': '
repeat 10
d = '0' + s / m
s = s - (s/m)*m
m = m / 10
if d <> '0'
z = 1
end if
if z <> 0
display d
end if
end repeat
display 13,10
}
macro movi arg1,arg2
{
if (arg1 in <eax,ebx,ecx,edx,esi,edi,ebp,esp>) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
if (arg2) = 0
xor arg1,arg1
else if (arg2) = 1
xor arg1,arg1
inc arg1
else if (arg2) = -1
or arg1,-1
else if (arg2) >= -128 & (arg2) <= 127
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
macro RGB [a] {
common
match (r=,g=,b),a \{
\dd ((r) shl 16) or ((g) shl 8) or (b)
\}
}
struc POINT _t,_dx,_dy {
.x _t _dx
.y _t _dy
}
; structure definition helper
include 'struct.inc'
struct RECT
left dd ?
top dd ?
right dd ?
bottom dd ?
ends
struct BOX
left dd ?
top dd ?
width dd ?
height dd ?
ends
; structures used in KolibriOS
struct process_information
cpu_usage dd ? ; +0
window_stack_position dw ? ; +4
window_stack_value dw ? ; +6
dw ? ; +8
process_name rb 12 ; +10
memory_start dd ? ; +22
used_memory dd ? ; +26
PID dd ? ; +30
box BOX ; +34
slot_state dw ? ; +50
dw ? ; +52
client_box BOX ; +54
wnd_state db ? ; +70
rb (1024-71)
ends
struct system_colors
frame dd ? ;nonset1
grab dd ? ;nonset2
work_dark dd ?
work_light dd ?
grab_text dd ? ;window_title
work dd ?
work_button dd ?
work_button_text dd ?
work_text dd ?
work_graph dd ?
ends
struct FILEDATE
Second db ?
Minute db ?
Hour db ?
db ?
Day db ?
Month db ?
Year dw ?
ends
struct FILEINFO
Attributes dd ?
IsUnicode db ?
db 3 dup(?)
DateCreate FILEDATE
DateAccess FILEDATE
DateModify FILEDATE
Size dq ?
ends
cmove fix cmovz
macro cmovz reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jnz ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovz reg1, reg2
end if
}
cmovne fix cmovnz
macro cmovnz reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jz ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovnz reg1, reg2
end if
}
macro cmovg reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jle ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovg reg1, reg2
end if
}
macro cmovl reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jge ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovl reg1, reg2
end if
}
; replaces /programs/cmp.inc
irp cond, e, ne, g, ng, l, nl, ge, le {
macro cmp#cond a, b, c\{
cmp a, b
j#cond c
\}
}
; constants
; events
EV_IDLE = 0
EV_TIMER = 0
EV_REDRAW = 1
EV_KEY = 2
EV_BUTTON = 3
EV_EXIT = 4
EV_BACKGROUND = 5
EV_MOUSE = 6
EV_IPC = 7
EV_STACK = 8
; event mask bits for function 40
EVM_REDRAW = 1b
EVM_KEY = 10b
EVM_BUTTON = 100b
EVM_EXIT = 1000b
EVM_BACKGROUND = 10000b
EVM_MOUSE = 100000b
EVM_IPC = 1000000b
EVM_STACK = 10000000b
EVM_DEBUG = 100000000b
EVM_STACK2 = 1000000000b
EVM_MOUSE_FILTER = 0x80000000
EVM_CURSOR_FILTER = 0x40000000

View File

@ -0,0 +1,301 @@
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ local loc
loc = (localbytes+3) and (not 3)
parmbase@proc equ ebp+8
localbase@proc equ ebp-loc
if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,loc
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
close@proc equ
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
virtual at parmbase@proc
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $-(parmbase@proc)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
macro locals
\{ virtual at localbase@proc+current
macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
current = $-(localbase@proc)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc
\{ localbytes = current
match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if qqword eq type
dd ?,?,?,?,?,?,?,?
else if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val] { name def val }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =?, val \{ ..tmp equ \}
match any (=?), val \{ ..tmp equ \}
match =label, def \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
struc label type { label . type }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count*2
restore done@local \\}
match =QQWORD, vartype \\{ label varname qqword
rq count*4
restore done@local \\}
match =XWORD, vartype \\{ label varname xword
rq count*2
restore done@local \\}
match =YWORD, vartype \\{ label varname yword
rq count*4
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match =QQWORD, vartype \\{ label varname qqword
dq ?,?,?,?
restore done@local \\}
match =XWORD, vartype \\{ label varname xword
dq ?,?
restore done@local \\}
match =YWORD, vartype \\{ label varname yword
dq ?,?,?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }

View File

@ -0,0 +1,240 @@
; Macroinstructions for defining data structures
macro struct name
{ virtual at 0
fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common define field@struct .,db,<val>
fields@struct equ fields@struct,field@struct \}
struc dw [val] \{ \common define field@struct .,dw,<val>
fields@struct equ fields@struct,field@struct \}
struc du [val] \{ \common define field@struct .,du,<val>
fields@struct equ fields@struct,field@struct \}
struc dd [val] \{ \common define field@struct .,dd,<val>
fields@struct equ fields@struct,field@struct \}
struc dp [val] \{ \common define field@struct .,dp,<val>
fields@struct equ fields@struct,field@struct \}
struc dq [val] \{ \common define field@struct .,dq,<val>
fields@struct equ fields@struct,field@struct \}
struc dt [val] \{ \common define field@struct .,dt,<val>
fields@struct equ fields@struct,field@struct \}
struc rb count \{ define field@struct .,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rw count \{ define field@struct .,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rd count \{ define field@struct .,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rp count \{ define field@struct .,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rq count \{ define field@struct .,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rt count \{ define field@struct .,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro db [val] \{ \common \local anonymous
define field@struct anonymous,db,<val>
fields@struct equ fields@struct,field@struct \}
macro dw [val] \{ \common \local anonymous
define field@struct anonymous,dw,<val>
fields@struct equ fields@struct,field@struct \}
macro du [val] \{ \common \local anonymous
define field@struct anonymous,du,<val>
fields@struct equ fields@struct,field@struct \}
macro dd [val] \{ \common \local anonymous
define field@struct anonymous,dd,<val>
fields@struct equ fields@struct,field@struct \}
macro dp [val] \{ \common \local anonymous
define field@struct anonymous,dp,<val>
fields@struct equ fields@struct,field@struct \}
macro dq [val] \{ \common \local anonymous
define field@struct anonymous,dq,<val>
fields@struct equ fields@struct,field@struct \}
macro dt [val] \{ \common \local anonymous
define field@struct anonymous,dt,<val>
fields@struct equ fields@struct,field@struct \}
macro rb count \{ \local anonymous
define field@struct anonymous,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rw count \{ \local anonymous
define field@struct anonymous,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rd count \{ \local anonymous
define field@struct anonymous,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rp count \{ \local anonymous
define field@struct anonymous,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rq count \{ \local anonymous
define field@struct anonymous,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rt count \{ \local anonymous
define field@struct anonymous,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \} }
macro ends
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
restruc rb,rw,rd,rp,rq,rt
purge db,dw,du,dd,dp,dq,dt
purge rb,rw,rd,rp,rq,rt
purge union,struct
match name tail,fields@struct, \\{ if $
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
err
end if \\}
match name=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
define fields@\\#name fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
macro make@struct name,[field,type,def]
{ common
local define
define equ name
forward
local sub
match , field \{ make@substruct type,name,sub def
define equ define,.,sub, \}
match any, field \{ define equ define,.#field,type,<def> \}
common
match fields, define \{ define@struct fields \} }
macro define@struct name,[field,type,def]
{ common
virtual
db `name
load initial@struct byte from 0
if initial@struct = '.'
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
err
end if
end virtual
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
label name#.#type
rb sizeof.#type
end if
local value
match any, list \{ list equ list, \}
list equ list <value>
common
sizeof.#name = $
restruc name
match values, list \{
struc name value \\{ \\local \\..base
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label \\..base
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ field type value
if ~ field eq .
rb sizeof.#name#field - ($-field)
end if \\\\}
common label . at \\..base \\\}
\\}
macro name value \\{
match any, fields@struct \\\{ \\\local anonymous
fields@struct equ fields@struct,anonymous,name,<values> \\\}
match , fields@struct \\\{
forward
match , value \\\\{ type def \\\\}
match any, value \\\\{ \\\\local ..field
..field = $
type value
if ~ field eq .
rb sizeof.#name#field - ($-..field)
end if \\\\}
common \\\} \\} \} }
macro enable@substruct
{ macro make@substruct substruct,parent,name,[field,type,def]
\{ \common
\local define
define equ parent,name
\forward
\local sub
match , field \\{ match any, type \\\{ enable@substruct
make@substruct type,parent,sub def
purge make@substruct
define equ define,.,sub, \\\} \\}
match any, field \\{ define equ define,.\#field,type,<def> \\}
\common
match fields, define \\{ define@\#substruct fields \\} \} }
enable@substruct
macro define@union parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
virtual at parent#.#name
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $ - parent#.#name
rb sizeof.#parent#field - ($ - parent#.#name)
end if
else
virtual at parent#.#name
label parent#.#type
type def
end virtual
label name#.#type at parent#.#name
if sizeof.#type > $ - parent#.#name
rb sizeof.#type - ($ - parent#.#name)
end if
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name [value] \{ \common
label .\#name
last@union equ
forward
match any, last@union \\{ virtual at .\#name
field type def
end virtual \\}
match , last@union \\{ match , value \\\{ field type def \\\}
match any, value \\\{ field type value \\\} \\}
last@union equ field
common rb sizeof.#name - ($ - .\#name) \}
macro name [value] \{ \common \local ..anonymous
..anonymous name value \} }
macro define@substruct parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
label parent#.#type
rb sizeof.#type
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name value \{
label .\#name
forward
match , value \\{ field type def \\}
match any, value \\{ field type value
if ~ field eq .
rb sizeof.#parent#field - ($-field)
end if \\}
common \}
macro name value \{ \local ..anonymous
..anonymous name \} }

View File

@ -0,0 +1,21 @@
#include <ctype.h>
unsigned short __is[129] = {
0, /* EOF */
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004,
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x140, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
0x459, 0x459, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x0D0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
0x253, 0x253, 0x253, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
0x0D0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
0x073, 0x073, 0x073, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x004
};

View File

@ -0,0 +1,121 @@
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/dirent.h>
#include <ksys.h>
ksys_coff_etable_t EXPORTS[] = {
{"abs", abs},
{"acos", acos},
{"acosh", acosh},
{"asin", asin},
{"asinh", asinh},
{"atan", atan},
{"atan2", atan2},
{"atanh", atanh},
{"atoi", atoi},
{"atol", atol},
{"atoll", atoll},
{"calloc", calloc},
{"ceil", ceil},
{"clearerr", clearerr},
{"closedir", closedir},
{"cos", cos},
{"cosh", cosh},
{"debug_printf", debug_printf},
{"difftime", difftime},
{"div", div},
{"exit", exit},
{"exp", exp},
{"fabs", fabs},
{"fclose", fclose},
{"feof", feof},
{"ferror", ferror},
{"fflush", fflush},
{"fgetc", fgetc},
{"fgetpos", fgetpos},
{"fgets", fgets},
{"floor", floor},
{"fmod", fmod},
{"fopen", fopen},
{"fputc", fputc},
{"fputs", fputs},
{"fread", fread},
{"free", free},
{"freopen", freopen},
{"frexp", frexp},
{"fseek", fseek},
{"fsetpos", fsetpos},
{"ftell", ftell},
{"fwrite", fwrite},
{"getchar", getchar},
{"gets", gets},
{"hypot", hypot},
{"labs", labs},
{"ldexp", ldexp},
{"ldiv", ldiv},
{"llabs", llabs},
{"lldiv", lldiv},
{"localtime", localtime},
{"log", log},
{"malloc", malloc},
{"memccpy", memccpy},
{"memchr", memchr},
{"memcmp", memcmp},
{"memcpy", memcpy},
{"memmove", memmove},
{"memset", memset},
{"mktime", mktime},
{"modf", modf},
{"modfl", modfl},
{"opendir", opendir},
{"perror", perror},
{"pow", pow},
{"pow10", pow10},
{"pow2", pow2},
{"printf", printf},
{"puts", puts},
{"readdir", readdir},
{"realloc", realloc},
{"remove", remove},
{"rename", rename},
{"rewind", rewind},
{"rewinddir", rewinddir},
{"seekdir", seekdir},
{"setbuf", setbuf},
{"setvbuf", setvbuf},
{"sin", sin},
{"sinh", sinh},
{"snprintf", snprintf},
{"sprintf", sprintf},
{"sqrt", sqrt},
{"strcat", strcat},
{"strchr", strchr},
{"strcmp", strcmp},
{"strcoll", strcoll},
{"strcpy", strcpy},
{"strcspn", strcspn},
{"strerror", strerror},
{"strlen", strlen},
{"strncat", strncat},
{"strncmp", strncmp},
{"strncpy", strncpy},
{"strpbrk", strpbrk},
{"strrchr", strrchr},
{"strrev", strrev},
{"strspn", strspn},
{"strstr", strstr},
{"strtok", strtok},
{"strxfrm", strxfrm},
{"tan", tan},
{"tanh", tanh},
{"telldir", telldir},
{"time", time},
{"tmpfile", tmpfile},
{"tmpnam", tmpnam},
{"vprintf", vprintf},
{"vsnprintf", vsnprintf},
0
};

View File

@ -0,0 +1,41 @@
#ifndef _CTYPE_H_
#define _CTYPE_H_
/*
** All character classification functions except isascii().
** Integer argument (c) must be in ASCII range (0-127) for
** dependable answers.
*/
#define __ALNUM 1
#define __ALPHA 2
#define __CNTRL 4
#define __DIGIT 8
#define __GRAPH 16
#define __LOWER 32
#define __PRINT 64
#define __PUNCT 128
#define __BLANK 256
#define __UPPER 512
#define __XDIGIT 1024
extern unsigned short __is[129];
#define isalnum(c)(__is[c+1] & __ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */
#define isalpha(c)(__is[c+1] & __ALPHA ) /* 'a'-'z', 'A'-'Z' */
#define iscntrl(c)(__is[c+1] & __CNTRL ) /* 0-31, 127 */
#define isdigit(c)(__is[c+1] & __DIGIT ) /* '0'-'9' */
#define isgraph(c)(__is[c+1] & __GRAPH ) /* '!'-'~' */
#define islower(c)(__is[c+1] & __LOWER ) /* 'a'-'z' */
#define isprint(c)(__is[c+1] & __PRINT ) /* ' '-'~' */
#define ispunct(c)(__is[c+1] & __PUNCT ) /* !alnum && !cntrl && !space */
#define isspace(c)(__is[c+1] & __BLANK ) /* HT, LF, VT, FF, CR, ' ' */
#define isupper(c)(__is[c+1] & __UPPER ) /* 'A'-'Z' */
#define isxdigit(c)(__is[c+1] & __XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */
#define isascii(c) (!((c)&(~0x7f)))
#define toascii(c) ((c)&0x7f)
extern unsigned char tolower(unsigned char c);
extern unsigned char toupper(unsigned char c);
#endif

View File

@ -0,0 +1,144 @@
#ifndef _ERRNO_H_
#define _ERRNO_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int _GLOBAL_VAR(errno);
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* Input/output error */
#define ENXIO 6 /* Device not configured */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file descriptor */
#define ECHILD 10 /* No child processes */
#define EDEADLK 11 /* Resource deadlock avoided */
/* 11 was EAGAIN */
#define ENOMEM 12 /* Cannot allocate memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device / Resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* Operation not supported by device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* Too many open files in system */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Inappropriate ioctl for device */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
/* math software */
#define EDOM 33 /* Numerical argument out of domain */
#define ERANGE 34 /* Result too large */
/* non-blocking and interrupt i/o */
#define EAGAIN 35 /* Resource temporarily unavailable */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define EINPROGRESS 36 /* Operation now in progress */
#define EALREADY 37 /* Operation already in progress */
/* ipc/network software -- argument errors */
#define ENOTSOCK 38 /* Socket operation on non-socket */
#define EDESTADDRREQ 39 /* Destination address required */
#define EMSGSIZE 40 /* Message too long */
#define EPROTOTYPE 41 /* Protocol wrong type for socket */
#define ENOPROTOOPT 42 /* Protocol not available */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
#define ENOTSUP 45 /* Operation not supported */
#define EOPNOTSUPP ENOTSUP /* Operation not supported on socket */
#define EPFNOSUPPORT 46 /* Protocol family not supported */
#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */
#define EADDRINUSE 48 /* Address already in use */
#define EADDRNOTAVAIL 49 /* Can't assign requested address */
/* ipc/network software -- operational errors */
#define ENETDOWN 50 /* Network is down */
#define ENETUNREACH 51 /* Network is unreachable */
#define ENETRESET 52 /* Network dropped connection on reset */
#define ECONNABORTED 53 /* Software caused connection abort */
#define ECONNRESET 54 /* Connection reset by peer */
#define ENOBUFS 55 /* No buffer space available */
#define EISCONN 56 /* Socket is already connected */
#define ENOTCONN 57 /* Socket is not connected */
#define ESHUTDOWN 58 /* Can't send after socket shutdown */
#define ETOOMANYREFS 59 /* Too many references: can't splice */
#define ETIMEDOUT 60 /* Operation timed out */
#define ECONNREFUSED 61 /* Connection refused */
#define ELOOP 62 /* Too many levels of symbolic links */
#define ENAMETOOLONG 63 /* File name too long */
/* should be rearranged */
#define EHOSTDOWN 64 /* Host is down */
#define EHOSTUNREACH 65 /* No route to host */
#define ENOTEMPTY 66 /* Directory not empty */
/* quotas & mush */
#define EPROCLIM 67 /* Too many processes */
#define EUSERS 68 /* Too many users */
#define EDQUOT 69 /* Disc quota exceeded */
/* Network File System */
#define ESTALE 70 /* Stale NFS file handle */
#define EREMOTE 71 /* Too many levels of remote in path */
#define EBADRPC 72 /* RPC struct is bad */
#define ERPCMISMATCH 73 /* RPC version wrong */
#define EPROGUNAVAIL 74 /* RPC prog. not avail */
#define EPROGMISMATCH 75 /* Program version wrong */
#define EPROCUNAVAIL 76 /* Bad procedure for program */
#define ENOLCK 77 /* No locks available */
#define ENOSYS 78 /* Function not implemented */
#define EFTYPE 79 /* Inappropriate file type or format */
#define EAUTH 80 /* Authentication error */
#define ENEEDAUTH 81 /* Need authenticator */
/* Intelligent device errors */
#define EPWROFF 82 /* Device power is off */
#define EDEVERR 83 /* Device error, e.g. paper out */
#define EOVERFLOW 84 /* Value too large to be stored in data type */
/* Program loading errors */
#define EBADEXEC 85 /* Bad executable */
#define EBADARCH 86 /* Bad CPU type in executable */
#define ESHLIBVERS 87 /* Shared library version mismatch */
#define EBADMACHO 88 /* Malformed Macho file */
#define ECANCELED 89 /* Operation canceled */
#define EIDRM 90 /* Identifier removed */
#define ENOMSG 91 /* No message of desired type */
#define EILSEQ 92 /* Illegal byte sequence */
#define ENOATTR 93 /* Attribute not found */
#define EBADMSG 94 /* Bad message */
#define EMULTIHOP 95 /* Reserved */
#define ENODATA 96 /* No message available on STREAM */
#define ENOLINK 97 /* Reserved */
#define ENOSR 98 /* No STREAM resources */
#define ENOSTR 99 /* Not a STREAM */
#define EPROTO 100 /* Protocol error */
#define ETIME 101 /* STREAM ioctl timeout */
#define ENOPOLICY 103 /* No such policy registered */
#define ENOTRECOVERABLE 104 /* State not recoverable */
#define EOWNERDEAD 105 /* Previous owner died */
#define EQFULL 106 /* Interface output queue is full */
#define ELAST 106 /* Must be equal largest errno */
#ifdef __cplusplus
}
#endif
#endif // _ERRNO_H_

View File

@ -0,0 +1,65 @@
#ifndef _FLOAT_H_
#define _FLOAT_H_
#define FLT_RADIX 2
/* IEEE float */
#define FLT_MANT_DIG 24
#define FLT_DIG 6
#define FLT_ROUNDS 1
#define FLT_EPSILON 1.19209290e-07F
#define FLT_MIN_EXP (-125)
#define FLT_MIN 1.17549435e-38F
#define FLT_MIN_10_EXP (-37)
#define FLT_MAX_EXP 128
#define FLT_MAX 3.40282347e+38F
#define FLT_MAX_10_EXP 38
/* IEEE double */
#define DBL_MANT_DIG 53
#define DBL_DIG 15
#define DBL_EPSILON 2.2204460492503131e-16
#define DBL_MIN_EXP (-1021)
#define DBL_MIN 2.2250738585072014e-308
#define DBL_MIN_10_EXP (-307)
#define DBL_MAX_EXP 1024
#define DBL_MAX 1.7976931348623157e+308
#define DBL_MAX_10_EXP 308
/* horrible intel long double */
#if defined __i386__ || defined __x86_64__
#define LDBL_MANT_DIG 64
#define LDBL_DIG 18
#define LDBL_EPSILON 1.08420217248550443401e-19L
#define LDBL_MIN_EXP (-16381)
#define LDBL_MIN 3.36210314311209350626e-4932L
#define LDBL_MIN_10_EXP (-4931)
#define LDBL_MAX_EXP 16384
#define LDBL_MAX 1.18973149535723176502e+4932L
#define LDBL_MAX_10_EXP 4932
#else
/* same as IEEE double */
#define LDBL_MANT_DIG 53
#define LDBL_DIG 15
#define LDBL_EPSILON 2.2204460492503131e-16
#define LDBL_MIN_EXP (-1021)
#define LDBL_MIN 2.2250738585072014e-308
#define LDBL_MIN_10_EXP (-307)
#define LDBL_MAX_EXP 1024
#define LDBL_MAX 1.7976931348623157e+308
#define LDBL_MAX_10_EXP 308
#endif
#ifndef NAN
# define NAN (__nan__)
#endif
#ifndef INFINITY
# define INFINITY (__inf__)
#endif
#endif /* _FLOAT_H_ */

View File

@ -0,0 +1,918 @@
#ifndef _KSYS_H_
#define _KSYS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#define asm_inline __asm__ __volatile__
#define not_optimized __attribute__((optimize("O0")))
typedef struct {
unsigned char blue;
unsigned char green;
unsigned char red;
}rgb_t;
#pragma pack(push,1)
typedef union{
unsigned val;
struct{
short x;
short y;
};
}ksys_pos_t;
typedef union ksys_oskey_t{
unsigned val;
struct{
unsigned char state;
unsigned char code;
unsigned char ctrl_key;
};
}ksys_oskey_t;
typedef struct{
unsigned handle;
unsigned io_code;
unsigned *input;
int inp_size;
void *output;
int out_size;
}ksys_ioctl_t;
typedef struct{
void *data;
size_t size;
}ksys_ufile_t;
typedef struct{
unsigned p00;
union{
uint64_t p04;
struct {
unsigned p04dw;
unsigned p08dw;
};
};
unsigned p12;
union {
unsigned p16;
const char *new_name;
void *bdfe;
void *buf16;
const void *cbuf16;
};
char p20;
const char *p21;
}ksys70_t;
typedef struct {
unsigned attributes;
unsigned name_cp;
char creation_time[4];
char creation_date[4];
char last_access_time[4];
char last_access_date[4];
char last_modification_time[4];
char last_modification_date[4];
unsigned long long size;
char name[0];
}ksys_bdfe_t;
typedef struct {
int cpu_usage; //+0
int window_pos_info; //+4
short int reserved1; //+8
char name[12]; //+10
int memstart; //+22
int memused; //+26
int pid; //+30
int winx_start; //+34
int winy_start; //+38
int winx_size; //+42
int winy_size; //+46
short int slot_info; //+50
short int reserved2; //+52
int clientx; //+54
int clienty; //+58
int clientwidth; //+62
int clientheight; //+66
unsigned char window_state;//+70
char reserved3[1024-71]; //+71
}ksys_proc_table_t;
typedef unsigned int ksys_color_t;
typedef struct{
ksys_color_t frame_area;
ksys_color_t grab_bar;
ksys_color_t grab_bar_button;
ksys_color_t grab_button_text;
ksys_color_t grab_text;
ksys_color_t work_area;
ksys_color_t work_button;
ksys_color_t work_button_text;
ksys_color_t work_text;
ksys_color_t work_graph;
}ksys_colors_table_t;
typedef struct{
unsigned pid; // PID of sending thread
unsigned datalen; // data bytes
char *data; // data begin
}ksys_ipc_msg;
typedef struct{
unsigned lock; // nonzero is locked
unsigned used; // used bytes in buffer
ksys_ipc_msg *data; // data begin
}ksys_ipc_buffer;
typedef struct {
char* func_name;
void* func_ptr;
}ksys_coff_etable_t;
#pragma pack(pop)
enum KSYS_EVENTS {
KSYS_EVENT_NONE = 0, /* Event queue is empty */
KSYS_EVENT_REDRAW = 1, /* Window and window elements should be redrawn */
KSYS_EVENT_KEY = 2, /* A key on the keyboard was pressed */
KSYS_EVENT_BUTTON = 3, /* A button was clicked with the mouse */
KSYS_EVENT_DESKTOP = 5, /* Desktop redraw finished */
KSYS_EVENT_MOUSE = 6, /* Mouse activity (movement, button press) was detected */
KSYS_EVENT_IPC = 7, /* Interprocess communication notify */
KSYS_EVENT_NETWORK = 8, /* Network event */
KSYS_EVENT_DEBUG = 9, /* Debug subsystem event */
KSYS_EVENT_IRQBEGIN = 16 /* 16..31 IRQ0..IRQ15 interrupt =IRQBEGIN+IRQn */
};
enum KSYS_FILE_ENCODING{
KSYS_FILE_CP866 =1,
KSYS_FILE_UTF16LE = 2,
KSYS_FILE_UTF8 = 3
};
enum KSYS_CLIP_ENCODING{
KSYS_CLIP_UTF8 = 0,
KSYS_CLIP_CP866 = 1,
KSYS_CLIP_CP1251 = 2
};
enum KSYS_CLIP_TYPES{
KSYS_CLIP_TEXT = 0,
KSYS_CLIP_IMAGE = 1,
KSYS_CLIP_RAW = 2
};
static inline
int _ksys_strcmp(const char * s1, const char * s2 )
{
while ((*s1) && (*s1 == *s2)){
++s1;
++s2;
}
return ( *( unsigned char * )s1 - * ( unsigned char * )s2 );
}
// Functions for working with the graphical interface
static inline
void _ksys_start_draw()
{
asm_inline("int $0x40"::"a"(12),"b"(1));
}
static inline
void _ksys_end_draw()
{
asm_inline("int $0x40" ::"a"(12),"b"(2));
}
static inline
void _ksys_create_window(int x, int y, int w, int h, const char *name, ksys_color_t workcolor, unsigned style)
{
asm_inline(
"int $0x40"
::"a"(0),
"b"((x << 16) | ((w-1) & 0xFFFF)),
"c"((y << 16) | ((h-1) & 0xFFFF)),
"d"((style << 24) | (workcolor & 0xFFFFFF)),
"D"(name),
"S"(0) : "memory"
);
};
static inline
void _ksys_change_window(int new_x, int new_y, int new_w, int new_h)
{
asm_inline(
"int $0x40"
::"a"(67), "b"(new_x), "c"(new_y), "d"(new_w),"S"(new_h)
);
}
static inline
void _ksys_define_button(unsigned x, unsigned y, unsigned w, unsigned h, unsigned id, ksys_color_t color)
{
asm_inline(
"int $0x40"
::"a"(8),
"b"((x<<16)+w),
"c"((y<<16)+h),
"d"(id),
"S"(color)
);
};
static inline
void _ksys_draw_line(int xs, int ys, int xe, int ye, ksys_color_t color)
{
asm_inline(
"int $0x40"
::"a"(38), "d"(color),
"b"((xs << 16) | xe),
"c"((ys << 16) | ye)
);
}
static inline
void _ksys_draw_bar(int x, int y, int w, int h, ksys_color_t color)
{
asm_inline(
"int $0x40"
::"a"(13), "d"(color),
"b"((x << 16) | w),
"c"((y << 16) | h)
);
}
static inline
void _ksys_draw_bitmap(void *bitmap, int x, int y, int w, int h)
{
asm_inline(
"int $0x40"
::"a"(7), "b"(bitmap),
"c"((w << 16) | h),
"d"((x << 16) | y)
);
}
static inline
void _ksys_draw_text(const char *text, int x, int y, int len, ksys_color_t color)
{
asm_inline(
"int $0x40"
::"a"(4),"d"(text),
"b"((x << 16) | y),
"S"(len),"c"(color)
:"memory"
);
}
static inline
void _ksys_draw_text_bg(const char *text, int x, int y, int len, ksys_color_t color, ksys_color_t bg)
{
asm_inline(
"int $0x40"
::"a"(4),"d"(text),
"b"((x << 16) | y),
"S"(len),"c"(color), "D"(bg)
:"memory"
);
}
static inline
void _ksys_draw_number(int number, int x, int y, int len, ksys_color_t color){
unsigned fmt;
fmt = len << 16 | 0x80000000; // no leading zeros + width
asm_inline(
"int $0x40"
::"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color)
);
}
static inline
void _ksys_draw_number_bg(unsigned number, int x, int y, int len, ksys_color_t color, ksys_color_t bg){
unsigned fmt;
fmt = len << 16 | 0x80000000; // no leading zeros + width
asm_inline(
"int $0x40"
::"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color), "D"(bg)
);
}
static inline
unsigned _ksys_get_skin_height()
{
unsigned height;
asm_inline(
"int $0x40 \n\t"
:"=a"(height)
:"a"(48),"b"(4)
);
return height;
}
static inline
void _ksys_get_colors(ksys_colors_table_t *color_table)
{
asm_inline(
"int $0x40"
::"a"(48),"b"(3),"c"(color_table),"d"(40)
);
}
/* Functions for working with a mouse and cursors. */
static inline
ksys_pos_t _ksys_get_mouse_pos(int origin)
{
ksys_pos_t val;
asm_inline(
"int $0x40 \n\t"
"rol $16, %%eax"
:"=a"(val)
:"a"(37),"b"(origin)
);
return val;
}
static inline
unsigned _ksys_get_mouse_buttons()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(37),"b"(2)
);
return val;
}
static inline
unsigned _ksys_get_mouse_wheels()
{
unsigned val;
asm_inline(
"int $0x40 \n\t"
:"=a"(val)
:"a"(37),"b"(7)
);
return val;
}
static inline
unsigned _ksys_load_cursor(void *path, unsigned flags)
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(37), "b"(4), "c"(path), "d"(flags)
);
return val;
}
static inline
unsigned _ksys_set_cursor(unsigned cursor)
{
unsigned old;
asm_inline(
"int $0x40"
:"=a"(old)
:"a"(37), "b"(5), "c"(cursor)
);
return old;
}
static inline
int _ksys_destroy_cursor(unsigned cursor)
{
int ret;
asm_inline(
"int $0x40"
:"=a"(ret)
:"a"(37), "b"(6), "c"(cursor)
:"memory"
);
return ret;
}
static inline
unsigned _ksys_get_mouse_eventstate()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(37),"b"(3)
);
return val;
}
/* Functions for working with events and buttons. */
static inline
unsigned _ksys_set_event_mask(unsigned mask)
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(40), "b"(mask)
);
return val;
}
static inline
unsigned _ksys_wait_event(unsigned time)
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(23), "b"(time)
);
return val;
}
static inline
unsigned _ksys_check_event()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(11)
);
return val;
}
static inline
unsigned _ksys_get_event()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(10)
);
return val;
}
static inline
unsigned _ksys_get_button()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(17)
);
return val>>8;
}
static inline
ksys_oskey_t _ksys_get_key(void)
{
ksys_oskey_t val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(2)
);
return val;
}
/* Functions for working with the clipboard */
static inline
int _ksys_clip_num()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(54), "b"(0)
);
return val;
}
static inline
char* _ksys_clip_get(int n) // returned buffer must be freed by _ksys_free()
{
char* val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(54), "b"(1), "c"(n)
);
return val;
}
static inline
int _ksys_clip_set(int n, char *buffer)
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(54), "b"(2), "c"(n), "d"(buffer)
);
return val;
}
static inline
int _ksys_clip_pop()
{
unsigned val;
asm_inline (
"int $0x40"
:"=a"(val)
:"a"(54), "b"(3)
);
return val;
}
static inline
int _ksys_clip_unlock()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(54), "b"(4)
);
return val;
}
/* Working with time */
static inline
unsigned _ksys_get_tick_count()
{
unsigned val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(26),"b"(9)
);
return val;
}
static inline
uint64_t _ksys_get_ns_count()
{
uint64_t val;
asm_inline(
"int $0x40"
:"=A"(val)
:"a"(26), "b"(10)
);
return val;
}
static inline
void _ksys_delay(unsigned time)
{
asm_inline(
"int $0x40"
::"a"(5), "b"(time)
:"memory"
);
}
static inline
unsigned _ksys_get_date()
{
unsigned val;
asm_inline("int $0x40":"=a"(val):"a"(29));
return val;
}
static inline
unsigned _ksys_get_clock()
{
unsigned val;
asm_inline("int $0x40":"=a"(val):"a"(3));
return val;
}
/* Working with memory allocation */
static inline
void* _ksys_alloc(size_t size){
void *val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(12),"c"(size)
);
return val;
}
static inline
int _ksys_free(void *mem)
{
int val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(13),"c"(mem)
);
return val;
}
static inline
void* _ksys_realloc(void *mem, size_t size)
{
void *val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(20),"c"(size),"d"(mem)
:"memory"
);
return val;
}
static inline
int* _ksys_unmap(void *base, size_t offset, size_t size)
{
int *val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size)
);
return val;
}
/* Loading the dynamic coff library */
static inline
ksys_coff_etable_t* not_optimized _ksys_cofflib_load(const char* path)
{
ksys_coff_etable_t *table;
asm_inline(
"int $0x40"
:"=a"(table)
:"a"(68),"b"(19), "c"(path)
);
return table;
}
static inline
void* not_optimized _ksys_cofflib_getproc(ksys_coff_etable_t *table, const char* fun_name)
{
unsigned i=0;
while (1){
if (NULL == (table+i)->func_name){
break;
}else{
if (!_ksys_strcmp(fun_name, (table+i)->func_name)){
return (table+i)->func_ptr;
}
}
i++;
}
return NULL;
}
/* Debug board functions */
static inline
void _ksys_debug_putc(char c)
{
asm_inline("int $0x40"::"a"(63), "b"(1), "c"(c));
}
static inline
void _ksys_debug_puts(char *s)
{
unsigned i=0;
while (*(s+i)){
asm_inline ("int $0x40"::"a"(63), "b"(1), "c"(*(s+i)));
i++;
}
}
/* Working with threads and process */
static inline
int _ksys_start_thread(void* proc, char* stack_top)
{
int val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(51), "b"(1), "c"(proc), "d"(stack_top)
);
return val;
}
static inline
void _ksys_focus_window(int slot){
asm_inline(
"int $0x40"
::"a"(18), "b"(3), "c"(slot)
);
}
static inline
int _ksys_get_thread_slot(int tid){
int val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(18), "b"(21), "c"(tid)
);
return val;
}
static inline
int not_optimized _ksys_process_info(ksys_proc_table_t* table, int pid)
{
int val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(9), "b"(table), "c"(pid)
);
return val;
}
static inline
void _ksys_exit()
{
asm_inline("int $0x40"::"a"(-1));
}
/* Working with files and directories */
static inline
void _ksys_setcwd(char* dir){
asm_inline(
"int $0x40"
::"a"(30), "b"(1), "c"(dir)
);
}
static inline
int _ksys_getcwd(char* buf, int bufsize){
register int val;
asm_inline(
"int $0x40"
:"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize)
);
return val;
}
static inline
ksys_ufile_t _ksys_load_file(const char *path)
{
ksys_ufile_t uf;
asm_inline(
"int $0x40"
:"=a"(uf.data), "=d"(uf.size)
:"a"(68), "b"(27),"c"(path)
);
return uf;
}
static inline
ksys_ufile_t _ksys_load_file_enc(const char *path, unsigned file_encoding)
{
ksys_ufile_t uf;
asm_inline(
"int $0x40"
:"=a"(uf.data), "=d"(uf.size)
:"a"(68), "b"(28),"c"(path), "d"(file_encoding)
);
return uf;
}
static inline
int not_optimized _ksys_work_files(const ksys70_t *k)
{
int status;
asm_inline(
"int $0x40"
:"=a"(status)
:"a"(70), "b"(k)
);
return status;
}
static inline
int not_optimized _ksys_file_read_file(const char *name, unsigned long long offset, unsigned size, void *buf, unsigned *bytes_read)
{
ksys70_t k;
k.p00 = 0;
k.p04 = offset;
k.p12 = size;
k.buf16 = buf;
k.p20 = 0;
k.p21 = name;
int status;
unsigned bytes_read_v;
asm_inline(
"int $0x40"
:"=a"(status), "=b"(bytes_read_v)
:"a"(70), "b"(&k)
);
if (!status) {
*bytes_read = bytes_read_v;
}
return status;
}
static inline
int not_optimized _ksys_file_write_file(const char *name, unsigned long long offset, unsigned size, const void *buf, unsigned *bytes_written)
{
ksys70_t k;
k.p00 = 3;
k.p04 = offset;
k.p12 = size;
k.cbuf16 = buf;
k.p20 = 0;
k.p21 = name;
int status;
unsigned bytes_written_v;
asm_inline(
"int $0x40"
:"=a"(status), "=b"(bytes_written_v)
:"a"(70), "b"(&k)
);
if (!status) {
*bytes_written = bytes_written_v;
}
return status;
}
static inline
int not_optimized _ksys_file_get_info(const char *name, ksys_bdfe_t *bdfe)
{
ksys70_t k;
k.p00 = 5;
k.bdfe = bdfe;
k.p20 = 0;
k.p21 = name;
return _ksys_work_files(&k);
}
static inline
int not_optimized _ksys_file_delete(const char *name)
{
ksys70_t k;
k.p00 = 8;
k.p20 = 0;
k.p21 = name;
return _ksys_work_files(&k);
}
static inline
int not_optimized _ksys_file_rename(const char *name, const char *new_name)
{
ksys70_t k;
k.p00 = 10;
k.new_name = new_name;
k.p20 = 0;
k.p21 = name;
return _ksys_work_files(&k);
}
static inline
int not_optimized _ksys_exec(char *app_name, char *args){
ksys70_t file_op;
file_op.p00 = 7;
file_op.p04dw = 0;
file_op.p08dw = (unsigned)args;
file_op.p21 = app_name;
register int val;
asm_inline(
"int $0x40"
:"=a"(val)
:"a"(70), "b"(&file_op)
);
return val;
}
#endif // _KSYS_H_

View File

@ -0,0 +1,18 @@
#ifndef _LIMITS_H_
#define _LIMITS_H_
#define INT_MAX 2147483647
#define UINT_MAX (INT_MAX * 2U + 1)
#ifndef ARG_MAX
#define ARG_MAX 4096
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#endif /* _LIMITS_H_ */

View File

@ -0,0 +1,171 @@
/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#ifndef _MATH_H_
#define _MATH_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
extern double _FUNC(acos)(double _x);
extern double _FUNC(asin)(double _x);
extern double _FUNC(atan)(double _x);
extern double _FUNC(atan2)(double _y, double _x);
extern double _FUNC(ceil)(double _x);
extern double _FUNC(cos)(double _x);
extern double _FUNC(cosh)(double _x);
extern double _FUNC(exp)(double _x);
extern double _FUNC(fabs)(double _x);
extern double _FUNC(floor)(double _x);
extern double _FUNC(fmod)(double _x, double _y);
extern double _FUNC(frexp)(double _x, int *_pexp);
extern double _FUNC(ldexp)(double _x, int _exp);
extern double _FUNC(log)(double _y);
extern double _FUNC(log10)(double _x);
extern double _FUNC(modf)(double _x, double *_pint);
extern double _FUNC(pow)(double _x, double _y);
extern double _FUNC(sin)(double _x);
extern double _FUNC(sinh)(double _x);
extern double _FUNC(sqrt)(double _x);
extern double _FUNC(tan)(double _x);
extern double _FUNC(tanh)(double _x);
#define M_E 2.7182818284590452354
#define M_LOG2E 1.4426950408889634074
#define M_LOG10E 0.43429448190325182765
#define M_LN2 0.69314718055994530942
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.78539816339744830962
#define M_1_PI 0.31830988618379067154
#define M_2_PI 0.63661977236758134308
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT1_2 0.70710678118654752440
#define PI M_PI
#define PI2 M_PI_2
extern double _FUNC(acosh)(double);
extern double _FUNC(asinh)(double);
extern double _FUNC(atanh)(double);
extern double _FUNC(cbrt)(double);
extern double _FUNC(exp10)(double _x);
extern double _FUNC(exp2)(double _x);
extern double _FUNC(expm1)(double);
extern double _FUNC(hypot)(double, double);
extern double _FUNC(log1p)(double);
extern double _FUNC(log2)(double _x);
extern long double _FUNC(modfl)(long double _x, long double *_pint);
extern double _FUNC(pow10)(double _x);
extern double _FUNC(pow2)(double _x);
extern double _FUNC(powi)(double, int);
extern void _FUNC(sincos)(double, double *, double *);
/* These are in libm.a (Cygnus). You must link -lm to get these */
/* See libm/math.h for comments */
#ifndef __cplusplus
struct exception {
int type;
const char *name;
double arg1;
double arg2;
double retval;
int err;
};
#endif
extern double _FUNC(erf)(double);
extern double _FUNC(erfc)(double);
extern double _FUNC(gamma)(double);
extern int _FUNC(isinf)(double);
extern int _FUNC(isnan)(double);
extern int _FUNC(finite)(double);
extern double _FUNC(j0)(double);
extern double _FUNC(j1)(double);
extern double _FUNC(jn)(int, double);
extern double _FUNC(lgamma)(double);
extern double _FUNC(nan)(const char*);
extern double _FUNC(y0)(double);
extern double _FUNC(y1)(double);
extern double _FUNC(yn)(int, double);
extern double _FUNC(logb)(double);
extern double _FUNC(nextafter)(double, double);
extern double _FUNC(remainder)(double, double);
extern double _FUNC(scalb)(double, double);
#ifndef __cplusplus
extern int _FUNC(matherr)(struct exception *);
#endif
extern double _FUNC(significand)(double);
extern double _FUNC(copysign)(double, double);
extern int _FUNC(ilogb)(double);
extern double _FUNC(rint)(double);
extern double _FUNC(scalbn)(double, int);
extern double _FUNC(drem)(double, double);
extern double _FUNC(gamma_r)(double, int *);
extern double _FUNC(lgamma_r)(double, int *);
extern float _FUNC(acosf)(float);
extern float _FUNC(asinf)(float);
extern float _FUNC(atanf)(float);
extern float _FUNC(atan2f)(float, float);
extern float _FUNC(cosf)(float);
extern float _FUNC(sinf)(float);
extern float _FUNC(tanf)(float);
extern float _FUNC(coshf)(float);
extern float _FUNC(sinhf)(float);
extern float _FUNC(tanhf)(float);
extern float _FUNC(expf)(float);
extern float _FUNC(frexpf)(float, int *);
extern float _FUNC(ldexpf)(float, int);
extern float _FUNC(logf)(float);
extern float _FUNC(log10f)(float);
extern float _FUNC(modff)(float, float *);
extern float _FUNC(powf)(float, float);
extern float _FUNC(sqrtf)(float);
extern float _FUNC(ceilf)(float);
extern float _FUNC(fabsf)(float);
extern float _FUNC(floorf)(float);
extern float _FUNC(fmodf)(float, float);
extern float _FUNC(erff)(float);
extern float _FUNC(erfcf)(float);
extern float _FUNC(gammaf)(float);
extern float _FUNC(hypotf)(float, float);
extern int _FUNC(isinff)(float);
extern int _FUNC(isnanf)(float);
extern int _FUNC(finitef)(float);
extern float _FUNC(j0f)(float);
extern float _FUNC(j1f)(float);
extern float _FUNC(jnf)(int, float);
extern float _FUNC(lgammaf)(float);
extern float _FUNC(nanf)(const char*);
extern float _FUNC(y0f)(float);
extern float _FUNC(y1f)(float);
extern float _FUNC(ynf)(int, float);
extern float _FUNC(acoshf)(float);
extern float _FUNC(asinhf)(float);
extern float _FUNC(atanhf)(float);
extern float _FUNC(cbrtf)(float);
extern float _FUNC(logbf)(float);
extern float _FUNC(nextafterf)(float, float);
extern float _FUNC(remainderf)(float, float);
extern float _FUNC(scalbf)(float, float);
extern float _FUNC(significandf)(float);
extern float _FUNC(copysignf)(float, float);
extern int _FUNC(ilogbf)(float);
extern float _FUNC(rintf)(float);
extern float _FUNC(scalbnf)(float, int);
extern float _FUNC(dremf)(float, float);
extern float _FUNC(expm1f)(float);
extern float _FUNC(log1pf)(float);
extern float _FUNC(gammaf_r)(float, int *);
extern float _FUNC(lgammaf_r)(float, int *);
#ifdef __cplusplus
}
#endif
#endif /* _MATH_H_ */

View File

@ -0,0 +1,17 @@
#ifndef _SETJMP_H_
#define _SETJMP_H_
#include <stddef.h>
typedef unsigned long __jmp_buf[6];
typedef struct __jmp_buf_tag {
__jmp_buf __jb;
unsigned long __fl;
unsigned long __ss[128/sizeof(long)];
} jmp_buf[1];
extern int _FUNC(setjmp)(jmp_buf env);
extern void _FUNC(longjmp)(jmp_buf env, int val);
#endif // _SETJMP_H_

View File

@ -0,0 +1,77 @@
#ifndef _STDARG_H_
#define _STDARG_H_
#include <stddef.h>
#ifdef __x86_64__
#ifndef _WIN64
//This should be in sync with the declaration on our lib/libtcc1.c
/* GCC compatible definition of va_list. */
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
union {
unsigned int overflow_offset;
char *overflow_arg_area;
};
char *reg_save_area;
} __va_list_struct;
typedef __va_list_struct va_list[1];
extern void _FUNC(__va_start)(__va_list_struct *ap, void *fp);
extern void* _FUNC(__va_arg)(__va_list_struct *ap, int arg_type, int size, int align);
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
#define va_arg(ap, type) \
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
#define va_copy(dest, src) (*(dest) = *(src))
#define va_end(ap)
#else /* _WIN64 */
typedef char *va_list;
#define va_start(ap,last) __builtin_va_start(ap,last)
#define va_arg(ap,type) (ap += 8, sizeof(type)<=8 ? *(type*)ap : **(type**)ap)
#define va_copy(dest, src) ((dest) = (src))
#define va_end(ap)
#endif
#elif __arm__
typedef char *va_list;
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
& ~(_tcc_alignof(type) - 1))
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
#define va_copy(dest, src) (dest) = (src)
#define va_end(ap)
#elif defined(__aarch64__)
typedef struct {
void *__stack;
void *__gr_top;
void *__vr_top;
int __gr_offs;
int __vr_offs;
} va_list;
#define va_start(ap, last) __va_start(ap, last)
#define va_arg(ap, type) __va_arg(ap, type)
#define va_end(ap)
#define va_copy(dest, src) ((dest) = (src))
#else /* __i386__ */
typedef char *va_list;
/* only correct for i386 */
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
#define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
#define va_copy(dest, src) (dest) = (src)
#define va_end(ap)
#endif
/* fix a buggy dependency on GCC in libio.h */
typedef va_list __gnuc_va_list;
#define _VA_LIST_DEFINED
#endif /* _STDARG_H */

View File

@ -0,0 +1,11 @@
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
/* ISOC99 boolean */
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
#endif /* _STDBOOL_H */

View File

@ -0,0 +1,39 @@
#ifndef _STDDEF_H_
#define _STDDEF_H_
typedef __SIZE_TYPE__ size_t;
typedef __PTRDIFF_TYPE__ ssize_t;
typedef __WCHAR_TYPE__ wchar_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __PTRDIFF_TYPE__ intptr_t;
typedef __SIZE_TYPE__ uintptr_t;
#ifndef __int8_t_defined
#define __int8_t_defined
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
#ifdef _DYNAMIC
#define _FUNC(func) (*func)
#define _GLOBAL_VAR(var) *var
#else
#define _FUNC(func) func
#define _GLOBAL_VAR(var) var
#endif
#define offsetof(type, field) ((size_t)&((type *)0)->field)
#endif /* _STDDEF_H_ */

View File

@ -0,0 +1,28 @@
#ifndef _STDINT_H_
#define _STDINT_H_
#include <stddef.h>
#define INT8_MIN (-128)
#define INT8_MAX (127)
#define UINT8_MAX (255)
#define INT16_MIN (-32768)
#define INT16_MAX (32767)
#define UINT16_MAX (65535)
#define INT32_MIN (-2147483647L-1)
#define INT32_MAX (2147483647L)
#define UINT32_MAX (4294967295UL)
#if __have_long64
#define INT64_MIN (-9223372036854775807L-1L)
#define INT64_MAX (9223372036854775807L)
#define UINT64_MAX (18446744073709551615U)
#elif __have_longlong64
#define INT64_MIN (-9223372036854775807LL-1LL)
#define INT64_MAX (9223372036854775807LL)
#define UINT64_MAX (18446744073709551615ULL)
#endif
#endif /* _STDINT_H_*/

View File

@ -0,0 +1,142 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _STDIO_H_
#define _STDIO_H_
#include <stdarg.h>
#include <stddef.h>
#include <ksys.h>
extern int _FUNC(puts)(const char *str);
extern int _FUNC(printf)(const char* format, ...);
extern int _FUNC(sprintf)(char* buffer, const char* format, ...);
extern int _FUNC(snprintf)(char* buffer, size_t count, const char* format, ...);
extern int _FUNC(vsnprintf)(char* buffer, size_t count, const char* format, va_list va);
extern int _FUNC(vprintf)(const char* format, va_list va);
extern void _FUNC(debug_printf)(const char* format, ...);
typedef size_t fpos_t;
#define _STDIO_F_R 1 << 0 // Read
#define _STDIO_F_W 1 << 1 // Write
#define _STDIO_F_A 1 << 2 // Append
#define _STDIO_F_X 1 << 3 // eXclusive
#define _STDIO_F_B 1 << 4 // Binary
typedef struct FILE_s {
char *name;
fpos_t position;
int error;
int eof;
int kind; // 0 - undiefned, 1 - text, 2 - binary
int orientation; // 0 - undiefned, 1 - byte, 2 - wide
int mode; // flags _STDIO_F_*
int append_offset; // do not seek before this point ("a" mode)
int __ungetc_emu_buff; // Uses __ungetc_emu (temporary solution!)
} FILE;
#define _IOFBF 0
#define _IOLBF 1
#define _IONBF 2
#define BUFSIZ 1024
#define EOF -1
#define FOPEN_MAX 0xffffffff
#define FILENAME_MAX 255
#define L_tmpnam FILENAME_MAX
#define SEEK_CUR 0
#define SEEK_END 1
#define SEEK_SET 2
#define TMP_MAX FOPEN_MAX
#define stderr 0is7ye
#define stdin 8yfg8e
#define stdout 7hdgys
extern int _FUNC(fgetc)(FILE *);
extern char* _FUNC(fgets)(char *restrict, int, FILE *restrict);
extern int _FUNC(fprintf)(FILE *restrict, const char *restrict, ...);
extern int _FUNC(fputc)(int, FILE *);
extern int _FUNC(fputs)(const char *restrict, FILE *restrict);
extern size_t _FUNC(fread)(void *restrict, size_t size, size_t count, FILE *restrict);
extern int _FUNC(fscanf)(FILE *restrict, const char *restrict, ...);
extern size_t _FUNC(fwrite)(const void *restrict, size_t size, size_t count, FILE *restrict);
extern int _FUNC(getc)(FILE *);
extern int _FUNC(getchar)(void);
extern int _FUNC(printf)(const char *restrict, ...);
extern int _FUNC(putc)(int, FILE *);
extern int _FUNC(putchar)(int);
extern int _FUNC(puts)(const char *);
extern int _FUNC(scanf)(const char *restrict, ...);
extern char* _FUNC(gets)(char *str);
//extern int _FUNC(ungetc)(int, FILE *);
extern int _FUNC(vfprintf)(FILE *restrict, const char *restrict, va_list);
extern int _FUNC(vfscanf)(FILE *restrict, const char *restrict, va_list);
extern int _FUNC(vprintf)(const char *restrict, va_list);
extern int _FUNC(vscanf)(const char *restrict, va_list);
extern int _FUNC(vsscanf)(const char *, const char*, va_list);
extern int _FUNC(remove)(const char *);
extern int _FUNC(rename)(const char *, const char *);
extern FILE* _FUNC(tmpfile)(void);
extern char* _FUNC(tmpnam)(char *);
extern int _FUNC(fclose)(FILE *);
extern int _FUNC(fflush)(FILE *);
extern FILE* _FUNC(fopen)(const char *restrict, const char *restrict);
extern FILE* _FUNC(freopen)(const char *restrict, const char *restrict, FILE *restrict);
extern void _FUNC(setbuf)(FILE *restrict, char *restrict);
extern int _FUNC(setvbuf)(FILE *restrict, char *restrict, int, size_t);
extern int _FUNC(fgetpos)(FILE *restrict, fpos_t *restrict);
extern int _FUNC(fseek)(FILE *, long, int);
extern int _FUNC(fsetpos)(FILE *, const fpos_t *);
extern long _FUNC(ftell)(FILE *);
extern void _FUNC(rewind)(FILE *);
extern void _FUNC(clearerr)(FILE *);
extern int _FUNC(feof)(FILE *);
extern int _FUNC(ferror)(FILE *);
extern void _FUNC(perror)(const char *);
extern size_t _FUNC(fread)(void *restrict, size_t, size_t, FILE *restrict);
extern int _FUNC(getchar)(void);
#endif // _STDIO_H_

View File

@ -0,0 +1,38 @@
#ifndef _STDLIB_H_
#define _STDLIB_H_
#include <stddef.h>
#define RAND_MAX 65535
#ifndef NULL
# define NULL ((void*)0)
#endif
#define min(a, b) ((a)<(b) ? (a) : (b))
#define max(a, b) ((a)>(b) ? (a) : (b))
extern int _FUNC(atoi)(const char *s);
extern long _FUNC(atol)(const char *);
extern long long _FUNC(atoll)(const char *);
//char* itoa)(int n, char* s);
extern int _FUNC(abs)(int);
extern long _FUNC(labs)(long);
extern long long _FUNC(llabs)(long long);
typedef struct { int quot, rem; } div_t;
typedef struct { long quot, rem; } ldiv_t;
typedef struct { long long quot, rem; } lldiv_t;
extern div_t _FUNC(div)(int, int);
extern ldiv_t _FUNC(ldiv)(long, long);
extern lldiv_t _FUNC(lldiv)(long long, long long);
extern void _FUNC(*malloc)(size_t size);
extern void* _FUNC(calloc)(size_t num, size_t size);
extern void* _FUNC(realloc)(void *ptr, size_t newsize);
extern void _FUNC(free)(void *ptr);
extern void _FUNC(exit)(int status);
#endif

View File

@ -0,0 +1,186 @@
/* String handling <string.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _STRING_H_
#define _STRING_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* String function conventions */
/*
In any of the following functions taking a size_t n to specify the length of
an array or size of a memory region, n may be 0, but the pointer arguments to
the call shall still be valid unless otherwise stated.
*/
/* Copying functions */
extern void* _FUNC(memccpy)(void *restrict dest, const void *restrict src, int c, size_t n);
/* Copy a number of n characters from the memory area pointed to by s2 to the
area pointed to by s1. If the two areas overlap, behaviour is undefined.
Returns the value of s1.
*/
extern void* _FUNC(memcpy)(void* s1, const void* s2, size_t n);
/* Copy a number of n characters from the memory area pointed to by s2 to the
area pointed to by s1. The two areas may overlap.
Returns the value of s1.
*/
extern void* _FUNC(memmove)(void* s1, const void* s2, size_t n);
/* Copy the character array s2 (including terminating '\0' byte) into the
character array s1.
Returns the value of s1.
*/
extern char* _FUNC(strcpy)(char* s1, const char* s2);
/* Copy a maximum of n characters from the character array s2 into the character
array s1. If s2 is shorter than n characters, '\0' bytes will be appended to
the copy in s1 until n characters have been written. If s2 is longer than n
characters, NO terminating '\0' will be written to s1. If the arrays overlap,
behaviour is undefined.
Returns the value of s1.
*/
extern char* _FUNC(strncpy)(char* s1, const char* s2, size_t n);
/* Concatenation functions */
/* Append the contents of the character array s2 (including terminating '\0') to
the character array s1 (first character of s2 overwriting the '\0' of s1). If
the arrays overlap, behaviour is undefined.
Returns the value of s1.
*/
extern char* _FUNC(strcat)(char* s1, const char* s2);
/* Append a maximum of n characters from the character array s2 to the character
array s1 (first character of s2 overwriting the '\0' of s1). A terminating
'\0' is ALWAYS appended, even if the full n characters have already been
written. If the arrays overlap, behaviour is undefined.
Returns the value of s1.
*/
extern char* _FUNC(strncat)(char* s1, const char* s2, size_t n);
/* Comparison functions */
/* Compare the first n characters of the memory areas pointed to by s1 and s2.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
*/
extern int _FUNC(memcmp)(const void * s1, const void* s2, size_t n);
/* Compare the character arrays s1 and s2.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
*/
extern int _FUNC(strcmp)(const char * s1, const char* s2);
/* Compare the character arrays s1 and s2, interpreted as specified by the
LC_COLLATE category of the current locale.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
TODO: Currently a dummy wrapper for strcmp() as PDCLib does not yet support
locales.
*/
extern int _FUNC(strcoll)(const char* s1, const char* s2);
/* Compare no more than the first n characters of the character arrays s1 and
s2.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
*/
extern int _FUNC(strncmp)(const char* s1, const char* s2, size_t n);
/* Transform the character array s2 as appropriate for the LC_COLLATE setting of
the current locale. If length of resulting string is less than n, store it in
the character array pointed to by s1. Return the length of the resulting
string.
*/
extern size_t _FUNC(strxfrm)(char* s1, const char* s2, size_t n);
/* Search functions */
/* Search the first n characters in the memory area pointed to by s for the
character c (interpreted as unsigned char).
Returns a pointer to the first instance found, or NULL.
*/
extern void* _FUNC(memchr)(const void* s, int c, size_t n);
/* Search the character array s (including terminating '\0') for the character c
(interpreted as char).
Returns a pointer to the first instance found, or NULL.
*/
extern char* _FUNC(strchr)(const char* s, int c);
/* Determine the length of the initial substring of character array s1 which
consists only of characters not from the character array s2.
Returns the length of that substring.
*/
extern size_t _FUNC(strcspn)(const char* s1, const char* s2);
/* Search the character array s1 for any character from the character array s2.
Returns a pointer to the first occurrence, or NULL.
*/
extern char* _FUNC(strpbrk)(const char* s1, const char* s2);
/* Search the character array s (including terminating '\0') for the character c
(interpreted as char).
Returns a pointer to the last instance found, or NULL.
*/
extern char* _FUNC(strrchr)(const char * s, int c );
/* Determine the length of the initial substring of character array s1 which
consists only of characters from the character array s2.
Returns the length of that substring.
*/
extern size_t _FUNC(strspn)(const char * s1, const char * s2);
/* Search the character array s1 for the substring in character array s2.
Returns a pointer to that sbstring, or NULL. If s2 is of length zero,
returns s1.
*/
extern char* _FUNC(strstr)(const char * s1, const char * s2);
/* In a series of subsequent calls, parse a C string into tokens.
On the first call to strtok(), the first argument is a pointer to the to-be-
parsed C string. On subsequent calls, the first argument is NULL unless you
want to start parsing a new string. s2 holds an array of separator characters
which can differ from call to call. Leading separators are skipped, the first
trailing separator overwritten with '\0'.
Returns a pointer to the next token.
WARNING: This function uses static storage, and as such is not reentrant.
*/
extern char* _FUNC(strtok)(char* s1, const char* s2);
/* Miscellaneous functions */
/* Write the character c (interpreted as unsigned char) to the first n
characters of the memory area pointed to by s.
Returns s.
*/
extern void* _FUNC(memset)(void* s, int c, size_t n);
/* Map an error number to a (locale-specific) error message string. Error
numbers are typically errno values, but any number is mapped to a message.
TODO: PDCLib does not yet support locales.
*/
extern char* _FUNC(strerror)(int errnum);
/* Returns the length of the string s (excluding terminating '\0').*/
extern size_t _FUNC(strlen)(const char * s);
/* The function reverses the sequence of characters in the string pointed to by str. */
extern char* _FUNC(strrev)(char *str);
/* The strdup function executes the function pointed to by the str argument. */
extern char* _FUNC(strdup)(const char *str);
#endif

View File

@ -0,0 +1,34 @@
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
#ifndef _DIRENT_H_
#define _DIRENT_H_
#include <stddef.h>
#include <limits.h>
#define IS_FOLDER 16
#define IS_FILE 0
typedef unsigned ino_t;
struct dirent{
ino_t d_ino; //File serial number.
char d_name[PATH_MAX]; // Name of entry.
unsigned d_type;
};
typedef struct{
struct dirent* objs;
ino_t pos;
ino_t num_objs;
}DIR;
int _FUNC(closedir)(DIR *dir);
DIR* _FUNC(opendir)(const char *path);
struct dirent* _FUNC(readdir)(DIR *);
void _FUNC(rewinddir)(DIR *dir);
void _FUNC(seekdir)(DIR *dir, unsigned pos);
unsigned _FUNC(telldir)(DIR *dir);
#endif // _DIRENT_H_

View File

@ -0,0 +1,244 @@
/* Copyright (C) 2019-2021 Logaev Maxim (turbocat2001), GPLv2 */
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include <stddef.h>
#include <ksys.h>
#include <errno.h>
// Socket Types
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define SOCK_RAW 3
// IP protocols
#define IPPROTO_IP 0
#define IPPROTO_ICMP 1
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define IPPROTO_RAW 255
// IP options
#define IP_TTL 2
// Address families
#define AF_UNSPEC 0
#define AF_LOCAL 1
#define AF_INET 2 // Default INET=IPv4
#define AF_INET4 2 // IPv4
#define AF_INET6 10 // IPv6
#define PF_UNSPEC AF_UNSPEC
#define PF_LOCAL AF_LOCAL
#define PF_INET4 AF_INET4
#define PF_INET6 AF_INET6
// internal definition
#define AI_SUPPORTED 0x40F
// for system function 76
#define API_ETH (0<<16)
#define API_IPv4 (1<<16)
#define API_ICMP (2<<16)
#define API_UDP (3<<16)
#define API_TCP (4<<16)
#define API_ARP (5<<16)
#define API_PPPOE (6<<16)
// Socket flags for user calls
#define MSG_NOFLAG 0
#define MSG_PEEK 0x02
#define MSG_DONTWAIT 0x40
// Socket levels
#define SOL_SOCKET 0xffff
//Socket options
#define SO_BINDTODEVICE (1<<9)
#define SO_NONBLOCK (1<<31)
#define PORT(X) (X<<8)
#pragma pack(push,1)
struct sockaddr{
unsigned short sin_family;
unsigned short sin_port;
unsigned int sin_addr;
unsigned long long sin_zero;
};
typedef struct{
unsigned int level;
unsigned int optionname;
unsigned int optlenght;
unsigned char options;
}optstruct;
#pragma pack(pop)
static inline
void _conv_socket_err(){
switch(errno){
case 1: errno = ENOBUFS; break;
case 2: errno = EINPROGRESS; break;
case 4: errno = EOPNOTSUPP; break;
case 6: errno = EWOULDBLOCK; break;
case 9: errno = ENOTCONN; break;
case 10: errno = EALREADY; break;
case 11: errno = EINVAL; break;
case 12: errno = EMSGSIZE; break;
case 18: errno = ENOMEM; break;
case 20: errno = EADDRINUSE; break;
case 61: errno = ECONNREFUSED; break;
case 52: errno = ECONNRESET; break;
case 56: errno = EISCONN; break;
case 60: errno = ETIMEDOUT; break;
case 54: errno = ECONNABORTED; break;
default: errno = 0; break;
}
}
static inline
int socket(int domain, int type, int protocol)
{
int socket;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(socket)
:"a"(75), "b"(0), "c"(domain), "d"(type), "S"(protocol)
);
_conv_socket_err();
return socket;
}
static inline
int close(int socket)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(1), "c"(socket)
);
_conv_socket_err();
return status;
}
static inline
int bind(int socket, const struct sockaddr *addres, int addres_len)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(2), "c"(socket), "d"(addres), "S"(addres_len)
);
_conv_socket_err();
return status;
}
static inline
int listen(int socket, int backlog)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(3), "c"(socket), "d"(backlog)
);
_conv_socket_err();
return status;
}
static inline
int connect(int socket, const struct sockaddr* address, int socket_len)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(4), "c"(socket), "d"(address), "S"(socket_len)
);
_conv_socket_err();
return status;
}
static inline int
accept(int socket, const struct sockaddr *address, int address_len)
{
int new_socket;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(new_socket)
:"a"(75), "b"(5), "c"(socket), "d"(address), "S"(address_len)
);
_conv_socket_err();
return new_socket;
}
static inline
int send(int socket, const void *message, size_t msg_len, int flag)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(6), "c"(socket), "d"(message), "S"(msg_len), "D"(flag)
);
_conv_socket_err();
return status;
}
static inline
int recv(int socket, void *buffer, size_t buff_len, int flag)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(7), "c"(socket), "d"(buffer), "S"(buff_len), "D"(flag)
);
_conv_socket_err();
return status;
}
static inline
int setsockopt(int socket,const optstruct* opt)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(8), "c"(socket),"d"(opt)
);
_conv_socket_err();
return status;
}
static inline
int getsockopt(int socket, optstruct* opt)
{
int status;
asm_inline(
"int $0x40"
:"=b"(errno), "=a"(status)
:"a"(75), "b"(9), "c"(socket),"d"(opt)
);
_conv_socket_err();
return status;
}
static inline
int socketpair(int *socket1, int *socket2)
{
asm_inline(
"int $0x40"
:"=b"(*socket2), "=a"(*socket1)
:"a"(75), "b"(10)
);
errno=*socket2;
_conv_socket_err();
return *socket1;
}
#endif //_SOCKET_H_

View File

@ -0,0 +1,30 @@
#ifndef _TIME_H_
#define _TIME_H_
#include <ksys.h>
typedef unsigned long int clock_t;
typedef unsigned long int time_t;
#define clock() _ksys_get_clock()
#define CLOCKS_PER_SEC 100
struct tm {
int tm_sec; /* seconds after the minute 0-61*/
int tm_min; /* minutes after the hour 0-59 */
int tm_hour; /* hours since midnight 0-23 */
int tm_mday; /* day of the month 1-31 */
int tm_mon; /* months since January 0-11 */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday 0-6 */
int tm_yday; /* days since January 1 0-365 */
int tm_isdst; /* Daylight Saving Time flag */
};
extern time_t _FUNC(mktime)(struct tm * timeptr);
extern time_t _FUNC(time)(time_t* timer);
extern struct tm * _FUNC(localtime)(const time_t * timer); /* non-standard! ignore parameter and return just time now, not generate tm_isdst, tm_yday, tm_wday == -1 */
extern double _FUNC(difftime)(time_t end, time_t beginning);
extern struct tm buffertime;
#endif

View File

@ -0,0 +1,22 @@
#include "libc/asm.h"
.text
LC0:
.double 0d1.00000000000000000000e+00
MK_C_SYM(acos)
fldl 4(%esp)
fld1
fsubp %st(0),%st(1)
fsqrt
fldl 4(%esp)
fld1
faddp %st(0),%st(1)
fsqrt
fpatan
fld %st(0)
faddp
ret

View File

@ -0,0 +1,8 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double
acosh(double x)
{
return log(x + sqrt(x*x - 1));
}

View File

@ -0,0 +1,14 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(asin)
fldl 4(%esp)
fld %st(0)
fmulp
fld1
fsubp
fsqrt
fldl 4(%esp)
fxch %st(1)
fpatan
ret

View File

@ -0,0 +1,9 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double
asinh(double x)
{
return x>0 ? log(x + sqrt(x*x + 1)) : -log(sqrt(x*x+1)-x);
}

View File

@ -0,0 +1,8 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(atan)
fldl 4(%esp)
fld1
fpatan
ret

View File

@ -0,0 +1,35 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
.data
.align 2
nan:
.long 0xffffffff
.byte 0xff
.byte 0xff
.byte 0xff
.byte 0x7f
.text
MK_C_SYM(atan2)
fldl 4(%esp)
fldl 12(%esp)
ftst
fnstsw %ax
sahf
jne doit
fxch %st(1)
ftst
fnstsw %ax
sahf
je isanan
fxch %st(1)
doit:
fpatan
ret
isanan:
movl $1,C_SYM(errno)
fstp %st(0)
fstp %st(0)
fldl nan
ret

View File

@ -0,0 +1,8 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double
atanh(double x)
{
return log((1+x)/(1-x)) / 2.0;
}

View File

@ -0,0 +1,24 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(ceil)
pushl %ebp
movl %esp,%ebp
subl $8,%esp
fstcw -4(%ebp)
fwait
movw -4(%ebp),%ax
andw $0xf3ff,%ax
orw $0x0800,%ax
movw %ax,-2(%ebp)
fldcw -2(%ebp)
fldl 8(%ebp)
frndint
fldcw -4(%ebp)
movl %ebp,%esp
popl %ebp
ret

View File

@ -0,0 +1,15 @@
#include "libc/asm.h"
L0:
.quad 0xffffffffffffffff
MK_C_SYM(cos)
fldl 4(%esp)
fcos
fstsw
sahf
jnp L1
fstp %st(0)
fldl L0
L1:
ret

View File

@ -0,0 +1,8 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double cosh(double x)
{
const double ebig = exp(fabs(x));
return (ebig + 1.0/ebig) / 2.0;
}

View File

@ -0,0 +1,31 @@
#include "libc/asm.h"
.data
LCW1:
.word 0
LCW2:
.word 0
LC0:
.double 0d1.0e+00
.text
MK_C_SYM(exp)
fldl 4(%esp)
fldl2e
fmulp
fstcw LCW1
fstcw LCW2
fwait
andw $0xf3ff,LCW2
orw $0x0400,LCW2
fldcw LCW2
fldl %st(0)
frndint
fldcw LCW1
fxch %st(1)
fsub %st(1),%st
f2xm1
faddl LC0
fscale
fstp %st(1)
ret

View File

@ -0,0 +1,6 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(fabs)
fldl 4(%esp)
fabs
ret

View File

@ -0,0 +1,24 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(floor)
pushl %ebp
movl %esp,%ebp
subl $8,%esp
fstcw -4(%ebp)
fwait
movw -4(%ebp),%ax
andw $0xf3ff,%ax
orw $0x0400,%ax
movw %ax,-2(%ebp)
fldcw -2(%ebp)
fldl 8(%ebp)
frndint
fldcw -4(%ebp)
movl %ebp,%esp
popl %ebp
ret

View File

@ -0,0 +1,29 @@
#include "libc/asm.h"
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
.data
LCW1:
.word 0
.align 4
.text
MK_C_SYM(fmod)
fldl 4(%esp)
fldl 12(%esp)
ftst
fnstsw %ax
fxch %st(1)
sahf
jnz next
fstpl %st(0)
jmp out
next:
fprem
fnstsw %ax
sahf
jpe next
fstpl %st(1)
out:
ret

View File

@ -0,0 +1,26 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double
frexp(double x, int *exptr)
{
union {
double d;
unsigned char c[8];
} u;
u.d = x;
/*
* The format of the number is:
* Sign, 12 exponent bits, 51 mantissa bits
* The exponent is 1023 biased and there is an implicit zero.
* We get the exponent from the upper bits and set the exponent
* to 0x3fe (1022).
*/
*exptr = (int)(((u.c[7] & 0x7f) << 4) | (u.c[6] >> 4)) - 1022;
u.c[7] &= 0x80;
u.c[7] |= 0x3f;
u.c[6] &= 0x0f;
u.c[6] |= 0xe0;
return u.d;
}

View File

@ -0,0 +1,100 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*
* hypot() function for DJGPP.
*
* hypot() computes sqrt(x^2 + y^2). The problem with the obvious
* naive implementation is that it might fail for very large or
* very small arguments. For instance, for large x or y the result
* might overflow even if the value of the function should not,
* because squaring a large number might trigger an overflow. For
* very small numbers, their square might underflow and will be
* silently replaced by zero; this won't cause an exception, but might
* have an adverse effect on the accuracy of the result.
*
* This implementation tries to avoid the above pitfals, without
* inflicting too much of a performance hit.
*
*/
/// #include <float.h>
#include <math.h>
#include <errno.h>
/* Approximate square roots of DBL_MAX and DBL_MIN. Numbers
between these two shouldn't neither overflow nor underflow
when squared. */
#define __SQRT_DBL_MAX 1.3e+154
#define __SQRT_DBL_MIN 2.3e-162
double
hypot(double x, double y)
{
double abig = fabs(x), asmall = fabs(y);
double ratio;
/* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */
if (abig < asmall)
{
double temp = abig;
abig = asmall;
asmall = temp;
}
/* Trivial case. */
if (asmall == 0.)
return abig;
/* Scale the numbers as much as possible by using its ratio.
For example, if both ABIG and ASMALL are VERY small, then
X^2 + Y^2 might be VERY inaccurate due to loss of
significant digits. Dividing ASMALL by ABIG scales them
to a certain degree, so that accuracy is better. */
if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX)
return abig * sqrt(1.0 + ratio*ratio);
else
{
/* Slower but safer algorithm due to Moler and Morrison. Never
produces any intermediate result greater than roughly the
larger of X and Y. Should converge to machine-precision
accuracy in 3 iterations. */
double r = ratio*ratio, t, s, p = abig, q = asmall;
do {
t = 4. + r;
if (t == 4.)
break;
s = r / t;
p += 2. * s * p;
q *= s;
r = (q / p) * (q / p);
} while (1);
return p;
}
}
#ifdef TEST
#include <stdio.h>
int
main(void)
{
printf("hypot(3, 4) =\t\t\t %25.17e\n", hypot(3., 4.));
printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", hypot(3.e+150, 4.e+150));
printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", hypot(3.e+306, 4.e+306));
printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n",
hypot(3.e-320, 4.e-320));
printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n",
hypot(0.7*DBL_MAX, 0.7*DBL_MAX));
printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", hypot(DBL_MAX, 1.0));
printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", hypot(1.0, DBL_MAX));
printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", hypot(0.0, DBL_MAX));
return 0;
}
#endif

View File

@ -0,0 +1,32 @@
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double
ldexp(double v, int e)
{
double two = 2.0;
if (e < 0)
{
e = -e; /* This just might overflow on two-complement machines. */
if (e < 0) return 0.0;
while (e > 0)
{
if (e & 1) v /= two;
two *= two;
e >>= 1;
}
}
else if (e > 0)
{
while (e > 0)
{
if (e & 1) v *= two;
two *= two;
e >>= 1;
}
}
return v;
}

View File

@ -0,0 +1,9 @@
#ifndef __LIBC_ASM_H
#define __LIBC_ASM_H
#define C_SYM(x) x
// #define C_SYM(x) _##x
#define MK_C_SYM(x) .global C_SYM(x); C_SYM(x):
#endif

View File

@ -0,0 +1,7 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(log)
fldln2
fldl 4(%esp)
fyl2x
ret

View File

@ -0,0 +1,33 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
.text
#include "libc/asm.h"
MK_C_SYM(modf)
pushl %ebp
movl %esp,%ebp
subl $16,%esp
pushl %ebx
fnstcw -4(%ebp)
fwait
movw -4(%ebp),%ax
orw $0x0c3f,%ax
movw %ax,-8(%ebp)
fldcw -8(%ebp)
fwait
fldl 8(%ebp)
frndint
fstpl -16(%ebp)
fwait
movl -16(%ebp),%edx
movl -12(%ebp),%ecx
movl 16(%ebp),%ebx
movl %edx,(%ebx)
movl %ecx,4(%ebx)
fldl 8(%ebp)
fsubl -16(%ebp)
leal -20(%ebp),%esp
fclex
fldcw -4(%ebp)
fwait
popl %ebx
leave
ret

View File

@ -0,0 +1,22 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(__modfl)
MK_C_SYM(modfl)
pushl %ebp
movl %esp,%ebp
subl $4,%esp
fldt 8(%ebp)
movl 20(%ebp),%eax
fnstcw -2(%ebp)
movw -2(%ebp),%dx
orb $0x0c,%dh
movw %dx,-4(%ebp)
fldcw -4(%ebp)
fld %st(0)
frndint
fldcw -2(%ebp)
fld %st(0)
fstpt (%eax)
fsubrp %st,%st(1)
leave
ret

View File

@ -0,0 +1,86 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
.data
yint:
.word 0,0
LCW1:
.word 0
LCW2:
.word 0
.text
LC0:
.double 0d1.0e+00
frac:
fstcw LCW1
fstcw LCW2
fwait
andw $0xf3ff,LCW2
orw $0x0400,LCW2
fldcw LCW2
fldl %st(0)
frndint
fldcw LCW1
fxch %st(1)
fsub %st(1),%st
ret
Lpow2:
call frac
f2xm1
faddl LC0
fscale
fstp %st(1)
ret
MK_C_SYM(pow)
fldl 12(%esp)
fldl 4(%esp)
ftst
fnstsw %ax
sahf
jbe xltez
fyl2x
jmp Lpow2
xltez:
jb xltz
fstp %st(0)
ftst
fnstsw %ax
sahf
ja ygtz
jb error
fstp %st(0)
fld1
fchs
error:
fsqrt
ret
ygtz:
fstp %st(0)
fldz
ret
xltz:
fabs
fxch %st(1)
call frac
ftst
fnstsw %ax
fstp %st(0)
sahf
je yisint
fstp %st(0)
fchs
jmp error
yisint:
fistl yint
fxch %st(1)
fyl2x
call Lpow2
andl $1,yint
jz yeven
fchs
yeven:
ret

View File

@ -0,0 +1,33 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
.data
LCW1:
.word 0
LCW2:
.word 0
LC0:
.double 0d1.0e+00
.text
MK_C_SYM(__pow10)
MK_C_SYM(pow10)
fldl 4(%esp)
fldl2t
fmulp
fstcw LCW1
fstcw LCW2
fwait
andw $0xf3ff,LCW2
orw $0x0400,LCW2
fldcw LCW2
fldl %st(0)
frndint
fldcw LCW1
fxch %st(1)
fsub %st(1),%st
f2xm1
faddl LC0
fscale
fstp %st(1)
ret

View File

@ -0,0 +1,31 @@
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
.data
LCW1:
.word 0
LCW2:
.word 0
LC0:
.double 0d1.0e+00
.text
MK_C_SYM(__pow2)
MK_C_SYM(pow2)
fldl 4(%esp)
fstcw LCW1
fstcw LCW2
fwait
andw $0xf3ff,LCW2
orw $0x0400,LCW2
fldcw LCW2
fldl %st(0)
frndint
fldcw LCW1
fxch %st(1)
fsub %st(1),%st
f2xm1
faddl LC0
fscale
fstp %st(1)
ret

View File

@ -0,0 +1,16 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
L0:
.quad 0xffffffffffffffff
MK_C_SYM(sin)
fldl 4(%esp)
fsin
fstsw
sahf
jnp L1
fstp %st(0)
fldl L0
L1:
ret

View File

@ -0,0 +1,16 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double sinh(double x)
{
if(x >= 0.0)
{
const double epos = exp(x);
return (epos - 1.0/epos) / 2.0;
}
else
{
const double eneg = exp(-x);
return (1.0/eneg - eneg) / 2.0;
}
}

View File

@ -0,0 +1,6 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
MK_C_SYM(sqrt)
fldl 4(%esp)
fsqrt
ret

View File

@ -0,0 +1,16 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include "libc/asm.h"
L0:
.quad 0xffffffffffffffff
MK_C_SYM(tan)
fldl 4(%esp)
fptan
fstsw
fstp %st(0)
sahf
jnp L1
/* fstp %st(0) - if exception, there is nothing on the stack */
fldl L0
L1:
ret

View File

@ -0,0 +1,17 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <math.h>
double tanh(double x)
{
if (x > 50)
return 1;
else if (x < -50)
return -1;
else
{
const double ebig = exp(x);
const double esmall = 1.0/ebig;
return (ebig - esmall) / (ebig + esmall);
}
}

View File

@ -0,0 +1,15 @@
.global _longjmp
.global longjmp
_longjmp:
longjmp:
mov 4(%esp),%edx
mov 8(%esp),%eax
cmp $1,%eax
adc $0, %al
mov (%edx),%ebx
mov 4(%edx),%esi
mov 8(%edx),%edi
mov 12(%edx),%ebp
mov 16(%edx),%esp
jmp *20(%edx)

View File

@ -0,0 +1,20 @@
.global ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
___setjmp:
__setjmp:
_setjmp:
setjmp:
mov 4(%esp), %eax
mov %ebx, (%eax)
mov %esi, 4(%eax)
mov %edi, 8(%eax)
mov %ebp, 12(%eax)
lea 4(%esp), %ecx
mov %ecx, 16(%eax)
mov (%esp), %ecx
mov %ecx, 20(%eax)
xor %eax, %eax
ret

View File

@ -0,0 +1,6 @@
#include <stdio.h>
void clearerr(FILE *stream) {
stream->error = 0;
stream->eof = 0;
}

View File

@ -0,0 +1,56 @@
#include <ksys.h>
#include "conio.h"
static char* __con_caption = "Console application";
static char* __con_dllname = "/sys/lib/console.obj";
int __con_is_load = 0;
unsigned *__con_dll_ver;
void stdcall (*__con_init_hidden)(int wnd_width, int wnd_height,int scr_width, int scr_height, const char* title);
void stdcall (*__con_write_asciiz)(const char* str);
void stdcall (*__con_write_string)(const char* str, unsigned length);
int stdcall (*__con_getch)(void);
short stdcall (*__con_getch2)(void);
int stdcall (*__con_kbhit)(void);
char* stdcall (*__con_gets)(char* str, int n);
char* stdcall (*__con_gets2)(__con_gets2_callback callback, char* str, int n);
void stdcall (*__con_exit)(int status);
static void __con_lib_link(ksys_coff_etable_t *exp)
{
__con_dll_ver = _ksys_cofflib_getproc(exp, "con_dll_ver");
__con_init_hidden = _ksys_cofflib_getproc(exp, "con_init");
__con_write_asciiz = _ksys_cofflib_getproc(exp, "con_write_asciiz");
__con_write_string = _ksys_cofflib_getproc(exp, "con_write_string");
__con_getch = _ksys_cofflib_getproc(exp, "con_getch");
__con_getch2 = _ksys_cofflib_getproc(exp, "con_getch2");
__con_kbhit = _ksys_cofflib_getproc(exp, "con_kbhit");
__con_gets = _ksys_cofflib_getproc(exp, "con_gets");
__con_gets2 = _ksys_cofflib_getproc(exp, "con_gets2");
__con_exit = _ksys_cofflib_getproc(exp, "con_exit");
}
int __con_init(void)
{
return __con_init_opt(-1, -1, -1, -1, __con_caption);
}
int __con_init_opt(int wnd_width, int wnd_height,int scr_width, int scr_height, const char* title)
{
if(!__con_is_load){
ksys_coff_etable_t *__con_lib;
__con_lib = _ksys_cofflib_load(__con_dllname);
if(__con_lib==NULL){
_ksys_debug_puts("Error! Can't load console.obj lib\n");
return 1;
}
__con_lib_link(__con_lib);
__con_init_hidden(wnd_width, wnd_height, scr_width, scr_height, title);
__con_is_load= 1;
return 0;
}
return 1;
}

View File

@ -0,0 +1,76 @@
/*
This is adapded thunk for console.obj sys library
Only for internal use in stdio.h
Adapted for tcc by Siemargl, 2016
*/
#ifndef _CONIO_H_
#define _CONIO_H_
#define cdecl __attribute__ ((cdecl))
#define stdcall __attribute__ ((stdcall))
extern void stdcall (*__con_write_asciiz)(const char* str);
/* Display ASCIIZ-string to the console at the current position, shifting
the current position. */
extern void stdcall (*__con_write_string)(const char* str, unsigned length);
/* Similar to __con_write_asciiz, but length of the string must be given as a
separate parameter */
extern int stdcall (*__con_getch)(void);
/* Get one character from the keyboard.
For normal characters function returns ASCII-code. For extended
characters (eg, Fx, and arrows), first function call returns 0
and second call returns the extended code (similar to the DOS-function
input). Starting from version 7, after closing the console window,
this function returns 0. */
extern short stdcall (*__con_getch2)(void);
/* Reads a character from the keyboard. Low byte contains the ASCII-code
(0 for extended characters), high byte - advanced code (like in BIOS
input functions). Starting from version 7, after closing the console
window, this function returns 0. */
extern int stdcall (*__con_kbhit)(void);
/* Returns 1 if a key was pressed, 0 otherwise. To read pressed keys use
__con_getch and __con_getch2. Starting from version 6, after closing
the console window, this function returns 1. */
extern char* stdcall (*__con_gets)(char* str, int n);
/* Reads a string from the keyboard. Reading is interrupted when got
"new line" character, or after reading the (n-1) characters (depending on
what comes first). In the first case the newline is also recorded in the
str. The acquired line is complemented by a null character.
Starting from version 6, the function returns a pointer to the entered
line if reading was successful, and NULL if the console window was closed. */
typedef int (stdcall * __con_gets2_callback)(int keycode, char** pstr, int* pn,
int* ppos);
extern char* stdcall (*__con_gets2)(__con_gets2_callback callback, char* str, int n);
/* Con_gets completely analogous, except that when the user
press unrecognized key, it calls the specified callback-procedure
(which may, for example, handle up / down for history and tab to enter
autocompletion). You should pass to the procedure: key code and three pointers
- to the string, to the maximum length and to the current position.
function may change the contents of string and may change the string
itself (for example, to reallocate memory for increase the limit),
maximum length, and position of the line - pointers are passed for it.
Return value: 0 = line wasn't changed 1 = line changed, you should
remove old string and display new, 2 = line changed, it is necessary
to display it; 3 = immediately exit the function.
Starting from version 6, the function returns a pointer to the entered
line with the successful reading, and NULL if the console window was closed. */
extern int __con_is_load;
extern unsigned *__con_dll_ver;
extern int __con_init(void);
extern int __con_init_opt(int wnd_width, int wnd_height, int scr_width, int scr_height, const char* title);
extern void stdcall (*__con_exit)(int status);
#endif

View File

@ -0,0 +1,14 @@
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
#include <stdio.h>
#include <stdarg.h>
void debug_printf(const char *format,...)
{
va_list ap;
char log_board[300];
va_start (ap, format);
vsnprintf(log_board, 300, format, ap);
va_end(ap);
_ksys_debug_puts(log_board);
}

View File

@ -0,0 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
int fclose(FILE *stream) {
free(stream);
return 0;
}

View File

@ -0,0 +1,5 @@
#include <stdio.h>
int feof(FILE *stream) {
return stream->eof;
}

View File

@ -0,0 +1,5 @@
#include <stdio.h>
int ferror(FILE *stream) {
return stream->error;
}

View File

@ -0,0 +1,5 @@
#include <stdio.h>
int fflush(FILE *stream) {
return 0;
}

View File

@ -0,0 +1,11 @@
#include <stdio.h>
int fgetc(FILE* stream)
{
int c, rc;
rc = fread(&c, sizeof(char), 1, stream);
if(rc<1){
return EOF;
}
return c;
}

View File

@ -0,0 +1,6 @@
#include <stdio.h>
int fgetpos(FILE *restrict stream, fpos_t *restrict pos) {
*pos = stream->position;
return 0;
}

View File

@ -0,0 +1,24 @@
#include <stdio.h>
#include "conio.h"
#include <errno.h>
char *fgets(char *str, int n, FILE *stream)
{
int i=0, sym_code;
if(!stream || !str){
errno = EINVAL;
return NULL;
}
while (i<n-1){
sym_code = fgetc(stream);
if(sym_code =='\n' || sym_code == EOF){ break; }
str[i]=(char)sym_code;
i++;
}
if(i<1){ return NULL; }
return str;
}

View File

@ -0,0 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
FILE *fopen(const char *restrict _name, const char *restrict _mode) {
FILE *out = malloc(sizeof(FILE));
return freopen(_name, _mode, out);
}

View File

@ -0,0 +1,816 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
// embedded systems with a very limited resources. These routines are thread
// safe and reentrant!
// Use this instead of the bloated standard/newlib printf cause these use
// malloc for printf (and may not be thread safe).
//
///////////////////////////////////////////////////////////////////////////////
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "format_print.h"
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
#define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
#define PRINTF_SUPPORT_PTRDIFF_T
#endif
///////////////////////////////////////////////////////////////////////////////
// internal flag definitions
#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
#include <float.h>
#endif
// internal buffer output
void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
{
if (idx < maxlen) {
((char*)buffer)[idx] = character;
}
}
// internal null output
void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)character; (void)buffer; (void)idx; (void)maxlen;
}
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
{
const char* s;
for (s = str; *s && maxsize--; ++s);
return (unsigned int)(s - str);
}
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to unsigned int conversion
static unsigned int _atoi(const char** str)
{
unsigned int i = 0U;
while (_is_digit(**str)) {
i = i * 10U + (unsigned int)(*((*str)++) - '0');
}
return i;
}
// output the specified string in reverse, taking care of any zero-padding
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
{
const size_t start_idx = idx;
// pad spaces up to given width
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
for (size_t i = len; i < width; i++) {
out(' ', buffer, idx++, maxlen);
}
}
// reverse string
while (len) {
out(buf[--len], buffer, idx++, maxlen);
}
// append pad spaces up to given width
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) {
out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
// internal itoa format
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
// pad leading zeros
if (!(flags & FLAGS_LEFT)) {
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
// handle hash
if (flags & FLAGS_HASH) {
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
len--;
if (len && (base == 16U)) {
len--;
}
}
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'x';
}
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'X';
}
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'b';
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
buf[len++] = '0';
}
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
// internal itoa for 'long' type
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT)
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
#endif
// internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for special values
if (value != value)
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
return 0U;
#endif
}
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
// set default precision, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
buf[len++] = '0';
prec--;
}
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
if (diff > 0.5) {
++frac;
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
if (frac >= pow10[prec]) {
frac = 0;
++whole;
}
}
else if (diff < 0.5) {
}
else if ((frac == 0U) || (frac & 1U)) {
// if halfway, round up if odd OR if last digit is 0
++frac;
}
if (prec == 0U) {
diff = value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++whole;
}
}
else {
unsigned int count = prec;
// now do fractional part, as an unsigned number
while (len < PRINTF_FTOA_BUFFER_SIZE) {
--count;
buf[len++] = (char)(48U + (frac % 10U));
if (!(frac /= 10U)) {
break;
}
}
// add extra 0s
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
buf[len++] = '0';
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
// add decimal
buf[len++] = '.';
}
}
// do whole part, number is reversed
while (len < PRINTF_FTOA_BUFFER_SIZE) {
buf[len++] = (char)(48 + (whole % 10));
if (!(whole /= 10)) {
break;
}
}
// pad leading zeros
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
// check for NaN and special values
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
}
// determine the sign
const bool negative = value < 0;
if (negative) {
value = -value;
}
// default precision
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// determine the decimal exponent
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
union {
uint64_t U;
double F;
} conv;
conv.F = value;
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
if (value < conv.F) {
expval--;
conv.F /= 10;
}
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
if ((value >= 1e-4) && (value < 1e6)) {
if ((int)prec > expval) {
prec = (unsigned)((int)prec - expval - 1);
}
else {
prec = 0;
}
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
--prec;
}
}
}
// will everything fit?
unsigned int fwidth = width;
if (width > minwidth) {
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
// not enough characters, so go back to default sizing
fwidth = 0U;
}
if ((flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
// rescale the float value
if (expval) {
value /= conv.F;
}
// output the floating part
const size_t start_idx = idx;
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
// output the exponent part
if (minwidth) {
// output the exponential symbol
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
// output the exponent value
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
// internal vsnprintf
int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
{
unsigned int flags, width, precision, n;
size_t idx = 0U;
if (!buffer) {
// use null output function
out = _out_null;
}
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%') {
// no
out(*format, buffer, idx++, maxlen);
format++;
continue;
}
else {
// yes, evaluate it
format++;
}
// evaluate flags
flags = 0U;
do {
switch (*format) {
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
default : n = 0U; break;
}
} while (n);
// evaluate width field
width = 0U;
if (_is_digit(*format)) {
width = _atoi(&format);
}
else if (*format == '*') {
const int w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; // reverse padding
width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
format++;
}
// evaluate precision field
precision = 0U;
if (*format == '.') {
flags |= FLAGS_PRECISION;
format++;
if (_is_digit(*format)) {
precision = _atoi(&format);
}
else if (*format == '*') {
const int prec = (int)va_arg(va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
format++;
}
}
// evaluate length field
switch (*format) {
case 'l' :
flags |= FLAGS_LONG;
format++;
if (*format == 'l') {
flags |= FLAGS_LONG_LONG;
format++;
}
break;
case 'h' :
flags |= FLAGS_SHORT;
format++;
if (*format == 'h') {
flags |= FLAGS_CHAR;
format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't' :
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
#endif
case 'j' :
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
case 'z' :
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
default :
break;
}
// evaluate specifier
switch (*format) {
case 'd' :
case 'i' :
case 'u' :
case 'x' :
case 'X' :
case 'o' :
case 'b' : {
// set the base
unsigned int base;
if (*format == 'x' || *format == 'X') {
base = 16U;
}
else if (*format == 'o') {
base = 8U;
}
else if (*format == 'b') {
base = 2U;
}
else {
base = 10U;
flags &= ~FLAGS_HASH; // no hash for dec format
}
// uppercase
if (*format == 'X') {
flags |= FLAGS_UPPERCASE;
}
// no plus or space flag for u, x, X, o, b
if ((*format != 'i') && (*format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
// ignore '0' flag when precision is given
if (flags & FLAGS_PRECISION) {
flags &= ~FLAGS_ZEROPAD;
}
// convert the integer
if ((*format == 'i') || (*format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
const long long value = va_arg(va, long long);
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
const long value = va_arg(va, long);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
}
else {
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
}
}
format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// char output
out((char)va_arg(va, int), buffer, idx++, maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 's' : {
const char* p = va_arg(va, char*);
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// string output
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
out(*(p++), buffer, idx++, maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 'p' : {
width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
format++;
break;
}
case '%' :
out('%', buffer, idx++, maxlen);
format++;
break;
default :
out(*format, buffer, idx++, maxlen);
format++;
break;
}
}
// termination
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
// return written chars without terminating \0
return (int)idx;
}

View File

@ -0,0 +1,12 @@
#include <stddef.h>
#include <stdarg.h>
typedef struct {
void (*fct)(char character, void* arg);
void* arg;
} out_fct_wrap_type;
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
extern void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen);
extern void _out_null(char character, void* buffer, size_t idx, size_t maxlen);
extern int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va);

View File

@ -0,0 +1,403 @@
/*
function for format read from any source
Siemargl formats as http://www.cplusplus.com/reference/cstdio/scanf/, no wchar though
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html is used too
todo:
[characters], [^characters]
-%n nothing scanned, filled only if good result
-%d, i, u, o, x, p read similar - detect base by prefix 0 or 0x
-%a
-can overflow unsigned as signed
-radix point always '.', no LOCALEs
*/
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include "format_scan.h"
static int __try_parse_real(long double *real, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
// returns 1 if OK, -1 == EOF, -2 parse broken
{
int sign = 1, have_digits = 0;
long long div;
if (ch == '+')
{
ch = vgetc(save, src);
if (ch == EOF) return EOF;
} else
if (ch == '-')
{
sign = -1;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
};
*real = 0.0;
for (;;) // mantissa before point
{
// test ch is valid
if (isdigit(ch))
{
*real = *real * 10 + ch - '0';
have_digits++;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
} else
if (ch == '.' || ch == 'E' || ch == 'e')
{
break; // ok
}
else
{
vungetc(save, ch, src);
break;
}
}
if (ch != '.' && ch != 'E' && ch != 'e') // ok, just integer part
{
*real *= sign;
if (have_digits)
return 1;
else
return -2;
}
if(ch == '.')
{
ch = vgetc(save, src);
div = 10; // use as divisor
for (;;) // mantissa after point
{
// test ch is valid
if (isdigit(ch))
{
*real += (double)(ch - '0') / div;
div *= 10;
have_digits++;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
} else
if (ch == 'E' || ch == 'e')
{
break; // ok
}
else
{
vungetc(save, ch, src);
break;
}
}
if (ch != 'E' && ch != 'e') // ok, real as XX.YY
{
*real *= sign;
if (have_digits)
return 1;
else
return -2;
}
}
ch = vgetc(save, src);
*real *= sign;
// exponent
sign = 1;
if (ch == '+')
{
ch = vgetc(save, src);
if (ch == EOF) return EOF;
} else
if (ch == '-')
{
sign = -1;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
};
div = 0;
for (;;)
{
// test ch is valid
if (isdigit(ch))
{
div = div * 10 + ch - '0';
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
}
else
{
vungetc(save, ch, src);
break;
}
}
div *= sign;
*real *= pow(10, div);
return 1;
}
static int __try_parse_int(long long *digit, int ch, const void *src, void *save, virtual_getc vgetc, virtual_ungetc vungetc)
{
int sign = 1, base = 10, have_digits = 0;
if (ch == '+')
{
ch = vgetc(save, src);
if (ch == EOF) return EOF;
} else
if (ch == '-')
{
sign = -1;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
};
if (ch == '0') // octal or hex, read next
{
base = 8;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch))
have_digits++;
else
if (ch == 'x' || ch == 'X')
{
base = 16;
ch = vgetc(save, src);
if (ch == EOF) return EOF;
}
}
*digit = 0;
for (;;)
{
// test ch is valid
if ((isdigit(ch) && base == 10) ||
(isdigit(ch) && base == 8 && ch < '8') ||
(isxdigit(ch) && base == 16))
{
if (base == 16)
{
if (ch <= '9') ch-= '0';
else
if (ch <= 'F') ch = 10 + ch - 'A';
else
ch = 10 + ch - 'a';
}
else
ch -= '0';
*digit = *digit * base + ch;
have_digits++;
ch = vgetc(save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish num
}
else if (ch == EOF || isspace(ch))
break;
else
{
vungetc(save, ch, src);
break;
}
}
*digit *= sign;
if (have_digits)
return 1;
else
return -2;
}
int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc)
{
int i;
int length;
int fmt1, fmt2; // width, precision
size_t pos, posc;
const char *fmtc; // first point to %, fmtc points to specifier
int ch;
int format_flag;
int flag_long; // 2 = long double or long long int or wchar
int *point_to_n = NULL, nread = 0;
int flags; // parsed flags
int save = 0;
char *arg_str;
int *arg_int;
long *arg_long;
long long *arg_longlong;
float *arg_float;
double *arg_double;
long double *arg_longdouble;
long long digit;
long double real;
pos = 0;
while(*fmt)
{
while (*fmt && isspace(*fmt)) fmt++; // skip paces in format str
if (*fmt != '%') // usual char
{
ch = vgetc(&save, src);
if (ch != *fmt++) // char not match format
{
vungetc(&save, ch, src);
break;
}
pos++;
continue;
}
if (*(fmt + 1) == '%') // %%
{
ch = vgetc(&save, src);
if (ch != '%') // char not match format
{
vungetc(&save, ch, src);
break;
}
pos++;
fmt += 2;
continue;
}
//checking to containg format in the string
fmtc = fmt;
posc = pos;
flags = 0;
format_flag = 0;
flag_long = 0; // 2 = long double or long long int or wchar
while(*fmtc != '\0' && !format_flag) // searching end of format
{
fmtc++; posc++;
switch( *fmtc )
{
case 'a':
format_flag = 1;
flags |= flag_unsigned;
break;
case 'c': case 'd': case 'i': case 'e': case 'f': case 'g': case 's': case 'n':
format_flag = 1;
break;
case 'l':
flag_long = flag_long ? 2 : 1; // ll.eq.L
break;
case 'L':
flag_long = 2;
break;
case 'o': case 'u': case 'x': case 'p':
format_flag = 1;
flags |= flag_unsigned;
break;
case '*': case '.': // just skip
break;
default:
if(isdigit(*fmtc)) break;
goto exit_me; // non format char found - user error
}
}
if (format_flag == 0)
{
goto exit_me; // format char not found - user error
}
fmt1 = 0;
fmt2 = 0;
if (posc - pos > 1) // try to read width, precision
{
fmt++;
for(i = pos + 1; i < posc; i++)
{
switch(*fmt)
{
case '0':
if(fmt1 == 0 && (flags & flag_point) == 0) flags |= flag_lead_zeros;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if ((flags & flag_point) == 0)
fmt1 = fmt1 * 10 + (*fmt -'0');
else
fmt2 = fmt2 * 10 + (*fmt -'0');
break;
case '*': // ignoring
break;
case '.':
flags |= flag_point;
break;
case 'l': case 'L': // valid chars - skip
break;
default: // must be error
goto exit_me; // format char not found - user error
}
fmt++;
}
}
// do real work - format arguments values
// skip input spaces
do {
ch = vgetc(&save, src);
if (ch == EOF) goto exit_me;
} while (isspace(ch));
switch(*fmtc)
{
case 'n':
point_to_n = va_arg(argp, int*);
vungetc(&save, ch, src);
break;
case 'c': // read width chars, ever spaces
arg_str = va_arg(argp, char*);
if (fmt1 == 0) length = 1;
else length = fmt1;
for (i = 0; i < length;)
{
*arg_str++ = ch; i++;
ch = vgetc(&save, src);
if (ch == EOF) break;
}
if (i < length) goto exit_me; // not enough chars
break;
case 's':
arg_str = va_arg(argp, char*);
if (fmt1 == 0) length = 4095; // max string scan 4096
else length = fmt1;
for (i = 0; i < length; i++)
{
*arg_str++ = ch;
ch = vgetc(&save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish string
}
*arg_str++ = '\0';
break;
case 'd': case 'i': case 'u':
case 'o': case 'p': case 'x':
i = __try_parse_int(&digit, ch, src, &save, vgetc, vungetc);
if (i < 0) goto exit_me;
if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else
if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else
if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; }
break;
case 'a': case 'A': case 'f': case 'F':
case 'e': case 'E':
case 'g': case 'G':
i = __try_parse_real(&real, ch, src, &save, vgetc, vungetc);
if (i < 0) goto exit_me;
if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else
if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else
if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; }
break;
}
fmt = fmtc + 1;
nread++;
}
exit_me:
if (point_to_n) *point_to_n = nread;
return nread;
}

View File

@ -0,0 +1,20 @@
#include <stdio.h>
typedef int (*virtual_getc)(void *sp, const void *obj);
typedef void (*virtual_ungetc)(void *sp, int c, const void *obj);
enum flags_t
{
flag_unsigned = 0x02,
flag_register = 0x04,
flag_plus = 0x08,
flag_left_just = 0x10,
flag_lead_zeros = 0x20,
flag_space_plus = 0x40,
flag_hash_sign = 0x80,
flag_point = 0x100
};
extern char *__scanf_buffer;
int _format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vgetc, virtual_ungetc vungetc);

View File

@ -0,0 +1,9 @@
#include <stdio.h>
int fputc(int sym, FILE *stream)
{
if(!fwrite(&sym, sizeof(char), 1, stream)){
return EOF;
}
return sym;
}

View File

@ -0,0 +1,10 @@
#include <stdio.h>
#include <string.h>
int fputs(const char *str, FILE *stream){
int s_code;
for(int i=0; i<strlen(str) && s_code!=EOF; i++){
s_code = fputc(str[i], stream);
}
return s_code;
}

View File

@ -0,0 +1,16 @@
#include <stdio.h>
size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream) {
unsigned bytes_read = 0;
unsigned bytes_count = size * nmemb;
_ksys_file_read_file(stream->name, stream->position, bytes_count, ptr, &bytes_read);
stream->position += bytes_read;
ksys_bdfe_t info;
// TODO: Handle _ksys_file_get_info error somehow
if (!_ksys_file_get_info(stream->name, &info)) {
if (stream->position >= info.size) {
stream->eof = 1;
}
}
return bytes_read / size;
}

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *freopen(const char *restrict _name, const char *restrict _mode, FILE *restrict out) {
ksys_bdfe_t info;
if (_ksys_file_get_info(_name, &info)) {
return NULL;
}
if (!out) {
return NULL;
}
out->name = strdup(_name);
out->position = 0;
out->error = 0;
out->eof = 0;
out->kind = 0;
out->orientation = 0;
out->mode = 0;
if (strchr(_mode, 'b')) { out->mode |= _STDIO_F_B; }
if (strchr(_mode, 'x')) { out->mode |= _STDIO_F_X; }
if (strchr(_mode, 'a')) { out->mode |= _STDIO_F_A; }
if (strchr(_mode, 'r')) { out->mode |= _STDIO_F_R; }
if (strchr(_mode, 'w')) { out->mode |= _STDIO_F_W; }
if (strchr(_mode, '+')) { out->mode |= _STDIO_F_R | _STDIO_F_W; }
if (out->mode & _STDIO_F_A) {
out->position = info.size;
out->append_offset = info.size;
}
return out;
}

View File

@ -0,0 +1,13 @@
#include <stdio.h>
int fscanf(FILE* stream, const char* format, ...)
{
va_list arg;
int n;
va_start(arg, format);
n = vfscanf(stream, format, arg);
va_end(arg);
return n;
}

View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <ksys.h>
int fseek(FILE *stream, long int offset, int whence) {
if (whence == SEEK_SET) {
stream->position = offset;
} else if (whence == SEEK_CUR) {
stream->position += offset;
} else if (whence == SEEK_END) {
ksys_bdfe_t info;
if (_ksys_file_get_info(stream->name, &info)) {
return -1;
}
stream->position = info.size + offset;
}
stream->eof = 0;
}

View File

@ -0,0 +1,7 @@
#include <stdio.h>
int fsetpos(FILE *stream, const fpos_t *pos) {
stream->position = *pos;
stream->eof = 0;
return 0;
}

View File

@ -0,0 +1,5 @@
#include <stdio.h>
long int ftell(FILE *stream) {
return stream->position;
}

View File

@ -0,0 +1,16 @@
#include <stdio.h>
size_t fwrite(const void * restrict ptr,size_t size, size_t nmemb,FILE * restrict stream) {
unsigned bytes_written = 0;
unsigned bytes_count = size * nmemb;
_ksys_file_write_file(stream->name, stream->position, bytes_count, ptr, &bytes_written);
stream->position += bytes_written;
ksys_bdfe_t info;
// TODO: Handle _ksys_file_get_info error somehow
if (!_ksys_file_get_info(stream->name, &info)) {
if (stream->position >= info.size) {
stream->eof = 1;
}
}
return bytes_written / size;
}

View File

@ -0,0 +1,10 @@
#include <stdio.h>
#include "conio.h"
int getchar(void) {
int c = __con_getch();
if (c == 0) {
c = EOF;
}
return c;
}

View File

@ -0,0 +1,15 @@
#include <stdio.h>
#include <string.h>
#include "conio.h"
#include <errno.h>
char *gets(char* str)
{
__con_init();
if(__con_gets(str, 4096)==NULL){
errno = EIO;
return NULL;
}
str[strlen(str)-1]='\0';
return str;
}

View File

@ -0,0 +1,5 @@
#include <stdio.h>
void perror(const char *s) {
printf("%s: It's some error, maybe...", s);
}

View File

@ -0,0 +1,13 @@
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
#include <stdio.h>
#include <stdlib.h>
#include "format_print.h"
int printf(const char *format, ...)
{
va_list arg;
va_start(arg, format);
return vprintf(format, arg);
}

View File

@ -0,0 +1,13 @@
/* Copyright (C) 2021 Logaev Maxim (turbocat2001), GPLv2 */
#include <stdio.h>
#include <string.h>
#include "conio.h"
int puts(const char *str)
{
__con_init();
__con_write_asciiz(str);
__con_write_asciiz("\n");
return strlen(str);
}

View File

@ -0,0 +1,6 @@
#include <stdio.h>
#include <ksys.h>
int remove(const char *name) {
return _ksys_file_delete(name);
}

Some files were not shown because too many files have changed in this diff Show More