Added several functions (to ctype.h, stdlib.h)

"Optimised" some functions in string.h
Added dynamic libraries support based on sysfunction 68.19 (experimental)

git-svn-id: svn://kolibrios.org@215 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
victor 2006-11-21 12:36:25 +00:00
parent 00b8fb388c
commit 1391dd1d1d
28 changed files with 1632 additions and 195 deletions

View File

@ -0,0 +1 @@
compile.js clean

View File

@ -1,118 +1,128 @@
var fso=new ActiveXObject("Scripting.FileSystemObject");
var wsh=WScript.CreateObject("WScript.Shell");
var curpath=".";
var gccpath="c:\\program files\\MinGW\\MinGW\\bin\\";
//var gccpath="cmd.exe /c ";
var gccexe="\""+gccpath+"cc1.exe"+"\" ";
var asexe="\""+gccpath+"as.exe"+"\" ";
var objcopyexe="\""+gccpath+"objcopy.exe"+"\" ";
//var gccexe=gccpath+"cc1.exe" ;
//var asexe=gccpath+"as.exe";
var scriptline="CREATE melibc.a\r\n";
ForReading = 1
ForWriting = 2
ForAppending = 8
var fso = new ActiveXObject("Scripting.FileSystemObject");
var wsh = new ActiveXObject("WScript.Shell");
function alert(mes){WScript.Echo(mes);return mes}
function debug(obj){for(key in obj)alert('['+key+']="'+obj[key]+'"')}
function getFileContent(filename){
var file = fso.OpenTextFile(filename, ForReading);
var content = file.ReadAll();
file.close();
return content;
}
function include(filename){
eval(getFileContent(filename));
}
function Project(filename){
var text = getFileContent(filename);
eval("var config = {"+text+"};")
for(key in config) this[key] = config[key];
if(!this.files) this.files = [];
function getFileExt(name){
var i = name.lastIndexOf(".");
return (i==-1)? "" : name.substr(i);
}
this.getFileList = function(folder){
var f = fso.GetFolder(folder);
var fc = new Enumerator(f.SubFolders);
for (; !fc.atEnd(); fc.moveNext())
{
var name = fc.item()+"";
if(name[0]!='.' && !this.isIgnored(name))
this.getFileList(name);
}
delete fc;
fc = new Enumerator(f.Files);
for (; !fc.atEnd(); fc.moveNext())
{
var name = fc.item()+"";
if(name[0]!='.' && !this.isIgnored(name))
this.files.push(name);
}
}
this.clean = function(){
var fl = new Enumerator(this.files);
var fo;
for (; !fl.atEnd(); fl.moveNext()){
var file = fl.item()
switch(getFileExt(file)){
case ".o":
case ".s":
fo = fso.GetFile(file);
fo.Delete();
break;
}
}
delete fl;
}
var objList = [];
this.compile_asm = function(filename){
var objname = filename.replace(/.\w{1,3}$/,".o");
objList.push(objname);
if(fso.FileExists(objname)) return;
wsh.Run(this.fasm+' "'+filename+'" "'+objname+'"',0,true);
}
this.compile_c = function(filename){
var objname = filename.replace(/.\w{1,3}$/,".o");
objList.push(objname);
if(fso.FileExists(objname)) return;
var asmname = filename.replace(/.\w{1,3}$/,".s");
var command = "";
if(!fso.FileExists(asmname)){
command = this.gccpath +"\\"+ this.gccexe + " -nostdinc";
if(this.include) command += " -I .\\include";
command +=" -DGNUC" +' "'+filename + '" -o "' + asmname + '"';
wsh.Run("cmd.exe /c "+command, 0, true);
}
command = this.gccpath +"\\"+ this.asexe +' "'+ asmname +'" -o "'+ objname +'"';
wsh.Run("cmd.exe /c "+command, 0, true);
command = this.gccpath +"\\"+ this.objcopyexe +' -O elf32-i386 --remove-leading-char "'+ objname +'"';
wsh.Run("cmd.exe /c "+command, 0, true);
}
this.build = function(){
var fl = new Enumerator(this.files);
for (; !fl.atEnd(); fl.moveNext()){
var file = fl.item()
switch(getFileExt(file)){
case ".c": this.compile_c(file);break;
case ".asm": this.compile_asm(file);break;
case ".o": objList.push(file);break;
}
}
delete fl;
fl = new Enumerator(objList);
curpath=".\\string\\";
compileasm("memmove");
compileasm("memset");
curpath=".\\mesys\\";
compileasm("backgr");
compileasm("button");
compileasm("clock");
compileasm("date");
compileasm("debug_board");
compileasm("delay");
compileasm("dga");
compileasm("draw_bar");
compileasm("draw_image");
compileasm("draw_window");
compileasm("event");
compileasm("exit");
compileasm("file_58");
compileasm("ipc");
compileasm("irq");
compileasm("keyboard");
compileasm("line");
compileasm("midi");
compileasm("pci");
compileasm("pixel");
compileasm("process");
compileasm("screen");
compileasm("sound");
compileasm("thread");
compileasm("window_redraw");
compileasm("write_text");
curpath=".\\mem\\";
compileasm("memalloc");
curpath=".\\mesys\\";
compilec("debug_board_");
curpath=".\\string\\";
compilec("memchr");
compilec("memcmp");
compilec("strcat");
compilec("strchr");
compilec("strcmp");
compilec("strcoll");
compilec("strcpy");
compilec("strcspn");
compilec("strdup");
compilec("strerror");
compilec("strlen");
compilec("strnbrk");
compilec("strncat");
compilec("strncmp");
compilec("strncpy");
compilec("strrchr");
compilec("strspn");
compilec("strstr");
compilec("strtok");
compilec("strxfrm");
curpath=".\\file\\";
compilec("fclose");
compilec("fopen");
compilec("feof");
compilec("fflush");
compilec("fgetc");
compilec("fgetpos");
compilec("fsetpos");
compilec("fputc");
compilec("fread");
compilec("fwrite");
compilec("fseek");
compilec("ftell");
compilec("rewind");
compilec("fprintf");
compilec("fscanf");
compilec("ungetc");
curpath=".\\start\\";
compileasm("start");
//linking
scriptline+="SAVE\r\n";
linko();
function compileasm(filename)
{
wsh.Run("fasm.exe "+quote(curpath+filename+".asm")+
" "+quote(curpath+filename+".o"),0,true);
addo(filename);
}
function compilec(filename)
{
wsh.Run(gccexe+"-nostdinc -I .\\include -DGNUC " + quote(curpath + filename + ".c")+
" -o " + quote(curpath + filename + ".s"),0,true);
wsh.Run(asexe+quote(curpath+filename+".s")+" -o "+quote(curpath+filename+".o"),0,true);
wsh.Run(objcopyexe+" -O elf32-i386 --remove-leading-char "+quote(curpath+filename+".o"),0,true);
addo(filename);
}
function addo(filename)
{
scriptline+="ADDMOD "+curpath+filename+".o\r\n";
}
function linko()
{
//fso.DeleteFile(".\\melibc.a");
var file=fso.OpenTextFile("./script.txt",2,true);
file.Write(scriptline);
wsh.Run("cmd.exe /c ar.exe -M < ./script.txt",4,true);
}
function quote(name)
{
return "\""+name+"\"";
/* var file = fso.CreateTextFile("OBJLIST.TXT", true);
file.Write("CREATE "+this.dstpath+'\\'+this.name+".a\r\n");
for (; !fl.atEnd(); fl.moveNext()){file.Write("ADDMOD "+fl.item()+"\r\n");}
file.Write("SAVE\r\t");
file.Close();
wsh.Run(this.gccpath+"\\ar.exe -M < OBJLIST.TXT", 0, true);*/
var ar = wsh.Exec(this.gccpath+"\\ar.exe -M")
ar.StdIn.Write("CREATE "+this.dstpath+'\\'+this.name+".a\r\n");
for (; !fl.atEnd(); fl.moveNext()){ar.StdIn.Write("ADDMOD "+fl.item()+"\r\n");}
ar.StdIn.Write("SAVE\r\t");
}
this.rebuild = function(){
this.clean();
this.build();
}
this.isIgnored = function(value){
for(var i=0; i<this.ignored.length; i++)
if (this.ignored[i]==value||this.ignored[i]==getFileExt(value)) return true;
return false;
}
this.nothing = function(){alert("Hello")}
this.getFileList(this.srcpath);
}
try{var confFile = WScript.Arguments(1);}catch(e){var confFile = "make.cfg";}
try{var action = WScript.Arguments(0);}catch(e){var action = "build";}
var conf = new Project(confFile);
conf[action]();
if(conf.autoclean && action != "clean"){conf["clean"]();}
alert("Done");

View File

@ -0,0 +1,31 @@
/*
** 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 char _is[128];
#define isalnum(c)(_is[c] & ALNUM ) /* 'a'-'z', 'A'-'Z', '0'-'9' */
#define isalpha(c)(_is[c] & ALPHA ) /* 'a'-'z', 'A'-'Z' */
#define iscntrl(c)(_is[c] & CNTRL ) /* 0-31, 127 */
#define isdigit(c)(_is[c] & DIGIT ) /* '0'-'9' */
#define isgraph(c)(_is[c] & GRAPH ) /* '!'-'~' */
#define islower(c)(_is[c] & LOWER ) /* 'a'-'z' */
#define isprint(c)(_is[c] & PRINT ) /* ' '-'~' */
#define ispunct(c)(_is[c] & PUNCT ) /* !alnum && !cntrl && !space */
#define isspace(c)(_is[c] & BLANK ) /* HT, LF, VT, FF, CR, ' ' */
#define isupper(c)(_is[c] & UPPER ) /* 'A'-'Z' */
#define isxdigit(c)(_is[c] & XDIGIT) /* '0'-'9', 'a'-'f', 'A'-'F' */

View File

@ -2,9 +2,16 @@
#define mesys_h
#ifdef GNUC
#define stdcall __stdcall
#define cdecl __cdecl
#else
#define stdcall __attribute__ ((__stdcall))
#define cdecl __attribute__ ((__cdecl))
#endif
typedef unsigned long dword;
typedef unsigned char byte;
typedef unsigned short word;
extern void stdcall _msys_draw_window(int xcoord,int ycoord, int xsize,
int ysize,int workcolor,int type,
int captioncolor,int windowtype,int bordercolor);
@ -95,4 +102,8 @@ extern void stdcall _msys_window_redraw(int status);
extern void* malloc(int);
extern void free(void*);
extern void* realloc(void*,int);
extern dword* stdcall _msys_cofflib_load(char* name);
extern char* stdcall _msys_cofflib_getproc(void* exp,char* sz_name);
#endif

View File

@ -1,6 +1,7 @@
#ifndef stdio_h
#define stdio_h
#include "mesys.h"
#define NULL (void*)0
typedef struct {
char* buffer;
int buffersize;

View File

@ -0,0 +1,9 @@
//#define isspace(c) ((c)==' ')
#define abs(i) (((i)<0)?(-(i)):(i))
extern int atoib(char *s,int b);
extern int atoi(char *s);
extern char tolower(char c);
extern char toupper(char c);
extern void itoab(int n,char* s,int b);
extern void itoa(int n,char* s);

View File

@ -0,0 +1,12 @@
version: "0.0.1",
name: "melibc",
autoclean: false,
ignored: ["start"],
srcpath: ".",
dstpath: "..",
include: "include",
gccpath: "D:\\proganie\\MinGWStudio\\MinGW\\bin",
gccexe: "..\\libexec\\gcc\\mingw32\\3.4.2\\cc1.exe",
asexe: "as.exe",
fasm: "D:\\proganie\\FASM\\FASM.EXE",
objcopyexe: "objcopy.exe"

View File

@ -0,0 +1,156 @@
format ELF
section '.text' executable
public _msys_draw_window
_msys_draw_window:
;arg1 - xcoord
;arg2 - ycoord
;arg3 - xsize
;arg4 - ysize
;arg5 - workcolor
;arg6 - type
;arg7 - captioncolor
;arg8 - windowtype
;arg9 - bordercolor
push ebp
mov ebp,esp
push ebx esi edi
mov ebx,[ebp+8]
shl ebx,16
mov bx,[ebp+16]
mov ecx,[ebp+12]
shl ecx,16
mov cx,[ebp+20]
mov edx,[ebp+28]
shl edx,24
add edx,[ebp+24]
mov esi,[ebp+36]
shl esi,24
add esi,[ebp+32]
mov edi,[ebp+40]
xor eax,eax
int 0x40
pop edi esi ebx
pop ebp
ret
public _msys_read_file
_msys_read_file:
;arg1 - file name
;arg2 - file offset
;arg3 - size to read
;arg4 - data
;arg5 - temp buffer
;arg6 - file size
push ebp
mov ebp,esp
xor eax,eax
mov [file_struct.operation],eax
mov eax,[ebp+12]
mov [file_struct.offset],eax
mov eax,[ebp+16]
mov [file_struct.offset],eax
mov eax,[ebp+20]
mov [file_struct.offset],eax
mov [file_struct.temp_buffer],temp_buffer
mov edx,[ebp+8]
call copy_file_name
push ebx
mov ebx,file_struct
mov eax,58
int 0x40
mov ecx,[ebp+28]
test ecx,ecx
jz .no_file_size
mov [ecx],ebx
.no_file_size:
pop ebx
pop ebp
ret
copy_file_name:
push esi edi
cld
mov edi,edx
xor eax,eax
xor ecx,ecx
dec ecx
repnz scasb
not ecx
mov edi,file_struct.path
mov esi,edx
rep movsb
pop edi esi
ret
public _msys_write_file
_msys_write_file:
;arg1 - file name
;arg2 - size
;arg3 - data
push ebp
mov ebp,esp
xor eax,eax
mov [file_struct.offset],eax
inc eax
mov [file_struct.operation],eax
mov eax,[ebp+12]
mov [file_struct.size],eax
mov eax,[ebp+16]
mov [file_struct.data],eax
mov [file_struct.temp_buffer],temp_buffer
mov edx,[ebp+8]
call copy_file_name
push ebx
mov eax,58
mov ebx,file_struct
int 0x40
pop ebx
pop ebp
ret
public _msys_run_program
_msys_run_program:
;arg1 - program name
;arg2 - parameters
push ebp
mov ebp,esp
mov [file_struct.operation],16
xor eax,eax
mov [file_struct.offset],eax
mov [file_struct.data],eax
mov eax,[ebp+12]
mov [file_struct.param],eax
mov [file_struct.temp_buffer],temp_buffer;
mov edx,[ebp+8]
call copy_file_name
push ebx
mov eax,58
mov ebx,file_struct
int 0x40
pop ebx
pop ebp
ret
public _msys_debug_out
_msys_debug_out:
;arg1 - char to out
push ebx
mov ecx,[esp+8]
mov ebx,1
mov eax,63
int 0x40
pop ebx
ret
section '.data' writeable
section '.bss' writeable
file_struct:
.operation rd 1
.offset rd 1
.param:
.size rd 1
.data rd 1
.temp_buffer rd 1
.path rb 1024
temp_buffer rb 4096

View File

@ -0,0 +1,64 @@
format ELF
include 'proc32.inc'
section '.text' executable
;extrn 'malloc' as malloc:dword
extrn 'strncmp' as strncmp:dword
extrn 'debug_out_str' as debug_out_str
;extrn 'free' as free:dword
;extrn 'realloc' as realloc:dword
;extrn 'mf_init' as mf_init:dword
public _msys_cofflib_load
;public _msys_cofflib_link
public _msys_cofflib_getproc
proc _msys_cofflib_load stdcall, name:dword
mov eax, 68
mov ebx, 19
mov ecx, [name]
int 0x40
ret
endp
;align 4
;proc _msys_cofflib_link stdcall, exp:dword, imp:dword
; stdcall debug_out_str, szFuncLink
; mov esi, [imp]
; test esi, esi
; jz .done
;.next:
; lodsd
; test eax, eax
; jz .done
; stdcall _msys_cofflib_getproc, [exp], eax
; mov [esi-4], eax
; jmp .next
;.done:
; ret
;endp
align 4
proc _msys_cofflib_getproc stdcall, exp:dword, sz_name:dword
stdcall debug_out_str, szFuncGetProc
mov edx, [exp]
.next:
test edx, edx
jz .end
stdcall strncmp, [edx], [sz_name], 16
test eax, eax
jz .ok
add edx,8
jmp .next
.ok:
mov eax, [edx+4]
.end:
ret
endp
section '.data'
szFuncGetProc db 'somebody did call GetProc',0x0d, 0x0a,0
szFuncLink db 'somebody did call Link',0x0d, 0x0a,0

View File

@ -0,0 +1,268 @@
; 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
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
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) | (parmbytes=0)
retn
else
retn parmbytes
end if }
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 \}
virtual at ebp+8
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 =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,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,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
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-1) shr 2)+1) shl 2
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 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]
{ 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 =dup (=?), val \{ ..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 \} }
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+count
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 , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }

View File

@ -0,0 +1,7 @@
macro public_stdcall name,size
{
public name
public name#@#size
name:
name#@#size:
}

View File

@ -0,0 +1,422 @@
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-11-10
;
; For questions and bug reports, mail to mike.dld@gmail.com
;
; Available format specifiers are: %s, %d, %u, %x (with partial width support)
;
; to be defined:
; __DEBUG__ equ 1
; __DEBUG_LEVEL__ equ 5
macro debug_func name {
if used name
name@of@func equ name
}
macro debug_beginf {
align 4
name@of@func:
}
debug_endf fix end if
macro DEBUGS _sign,[_str] {
common
local tp
tp equ 0
match _arg:_num,_str \{
DEBUGS_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _str \{
DEBUGS_N _sign,,_arg
\}
}
macro DEBUGS_N _sign,_num,[_str] {
common
pushf
pushad
local ..str,..label,is_str
is_str = 0
forward
if _str eqtype ''
is_str = 1
end if
common
if is_str = 1
jmp ..label
..str db _str,0
..label:
add esp,4*8+4
mov edx,..str
sub esp,4*8+4
else
mov edx,_str
end if
if ~_num eq
if _num eqtype eax
if _num in <eax,ebx,ecx,edx,edi,ebp,esp>
mov esi,_num
else if ~_num eq esi
movzx esi,_num
end if
else if _num eqtype 0
mov esi,_num
else
local tp
tp equ 0
match [_arg],_num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =dword[_arg],tp _num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =word[_arg],tp _num \{
movzx esi,word[_arg]
tp equ 1
\}
match =0 =byte[_arg],tp _num \{
movzx esi,byte[_arg]
tp equ 1
\}
match =0,tp \{
'Error: specified string width is incorrect'
\}
end if
else
mov esi,0x7FFFFFFF
end if
call fdo_debug_outstr
popad
popf
}
macro DEBUGD _sign,_dec {
local tp
tp equ 0
match _arg:_num,_dec \{
DEBUGD_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _dec \{
DEBUGD_N _sign,,_arg
\}
}
macro DEBUGD_N _sign,_num,_dec {
pushf
pushad
if (~_num eq)
if (_dec eqtype eax | _dec eqtype 0)
'Error: precision allowed only for in-memory variables'
end if
if (~_num in <1,2,4>)
if _sign
'Error: 1, 2 and 4 are only allowed for precision in %d'
else
'Error: 1, 2 and 4 are only allowed for precision in %u'
end if
end if
end if
if _dec eqtype eax
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp>
mov eax,_dec
else if ~_dec eq eax
if _sign = 1
movsx eax,_dec
else
movzx eax,_dec
end if
end if
else if _dec eqtype 0
mov eax,_dec
else
add esp,4*8+4
if _num eq
mov eax,dword _dec
else if _num = 1
if _sign = 1
movsx eax,byte _dec
else
movzx eax,byte _dec
end if
else if _num = 2
if _sign = 1
movsx eax,word _dec
else
movzx eax,word _dec
end if
else
mov eax,dword _dec
end if
sub esp,4*8+4
end if
mov cl,_sign
call fdo_debug_outdec
popad
popf
}
macro DEBUGH _sign,_hex {
local tp
tp equ 0
match _arg:_num,_hex \{
DEBUGH_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _hex \{
DEBUGH_N _sign,,_arg
\}
}
macro DEBUGH_N _sign,_num,_hex {
pushf
pushad
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>)
'Error: 1..8 are only allowed for precision in %x'
end if
if _hex eqtype eax
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
if ~_hex eq eax
mov eax,_hex
end if
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax,_hex
end if
shl eax,16
if (_num eq)
mov edx,4
end if
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax,_hex
end if
shl eax,24
if (_num eq)
mov edx,2
end if
end if
else if _hex eqtype 0
mov eax,_hex
else
add esp,4*8+4
mov eax,dword _hex
sub esp,4*8+4
end if
if ~_num eq
mov edx,_num
else
mov edx,8
end if
call fdo_debug_outhex
popad
popf
}
;-----------------------------------------------------------------------------
debug_func fdo_debug_outchar
debug_beginf
pushad
mov cl,al
mov ebx,1
mov eax,63
int 0x40
popad
ret
debug_endf
debug_func fdo_debug_outstr
debug_beginf
mov eax,63
mov ebx,1
.l1: dec esi
js .l2
mov cl,[edx]
or cl,cl
jz .l2
int 0x40
inc edx
jmp .l1
.l2: ret
debug_endf
debug_func fdo_debug_outdec
debug_beginf
or cl,cl
jz @f
or eax,eax
jns @f
neg eax
push eax
mov al,'-'
call fdo_debug_outchar
pop eax
@@: push 10
pop ecx
push -'0'
.l1: xor edx,edx
div ecx
push edx
test eax,eax
jnz .l1
.l2: pop eax
add al,'0'
jz .l3
call fdo_debug_outchar
jmp .l2
.l3: ret
debug_endf
debug_func fdo_debug_outhex
__fdo_hexdigits db '0123456789ABCDEF'
debug_beginf
mov cl,dl
neg cl
add cl,8
shl cl,2
rol eax,cl
.l1: rol eax,4
push eax
and eax,0x0000000F
mov al,[__fdo_hexdigits+eax]
call fdo_debug_outchar
pop eax
dec edx
jnz .l1
ret
debug_endf
;-----------------------------------------------------------------------------
macro DEBUGF _level,_format,[_arg] {
common
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__
local ..f1,f2,a1,a2,c1,c2,c3,..lbl
_debug_str_ equ __debug_str_ # a1
a1 = 0
c2 = 0
c3 = 0
f2 = 0
repeat ..lbl-..f1
virtual at 0
db _format,0,0
load c1 word from %-1
end virtual
if c1 = '%s'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER S,a1,0,_arg
else if c1 = '%x'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER H,a1,0,_arg
else if c1 = '%d' | c1 = '%u'
local c4
if c1 = '%d'
c4 = 1
else
c4 = 0
end if
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER D,a1,c4,_arg
else if c1 = '\n'
c3 = c3 + 1
end if
end repeat
virtual at 0
db _format,0,0
load c1 from f2-c2
end virtual
if (c1<>0)&(f2<>..lbl-..f1-1)
DEBUGS 0,_debug_str_+f2-c2
end if
virtual at 0
..f1 db _format,0
..lbl:
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3
end virtual
end if
}
macro __include_debug_strings dummy,[_id,_fmt,_len] {
common
local c1,a1,a2
forward
if defined _len & ~_len eq
_id:
a1 = 0
a2 = 0
repeat _len
virtual at 0
db _fmt,0,0
load c1 word from %+a2-1
end virtual
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u')
db 0
a2 = a2 + 1
else if (c1='\n')
dw $0A0D
a1 = a1 + 1
a2 = a2 + 1
else
db c1 and 0x0FF
end if
end repeat
db 0
end if
}
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] {
common
local num
num = 0
forward
if num = _num
DEBUG#_letter _sign,_arg
end if
num = num+1
common
_num = _num+1
}
macro include_debug_strings {
if __DEBUG__ = 1
match dbg_str,__debug_strings \{
__include_debug_strings dbg_str
\}
end if
}

View File

@ -0,0 +1,337 @@
; language for programs
lang fix en ; ru en fr ge fi
@^ fix macro comment {
^@ fix }
; strings
macro sz name,[data] { ; from MFAR [mike.dld]
common
if used name
name db data
.size = $-name
end if
}
macro lsz name,[lng,data] { ; from MFAR [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] { ; from MFAR [mike.dld]
common
local s,m
m = 0
if used name
label name
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
.size = $-name
.maxl = m
end if
}
macro lszc name,elsz,[lng,data] { ; from MFAR [mike.dld]
common
local s,m
m = 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
end if
common
.size = $-name
.maxl = m
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
}
macro mcall a,b,c,d,e,f { ; mike.dld
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
int 0x40
}
; -------------------------
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,algn
{
local boundary
boundary = 16
if ~algn eq
boundary = algn
end if
align boundary
label name
}
macro func name {
if ~used name
display 'FUNC NOT USED: ',`name,13,10
else
align 4
name:
;pushad
;pushfd
;dps `name
;newline
;mcall 5,1
;popfd
;popad
}
macro endf { end if }
macro jif _op1,_cond,_op2,_label,_op
{
if _op eq
cmp _op1,_op2
else
_op _op1,_op2
end if
j#_cond _label
}
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
}
; optimize the code for size
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
macro add arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
inc arg1
else
add arg1,arg2
end if
else
add arg1,arg2
end if
}
macro sub arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
dec arg1
else
sub arg1,arg2
end if
else
sub arg1,arg2
end if
}
macro mov arg1,arg2
{
if (arg1 in __regs) & (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) < 128
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
struc POINT _t,_dx,_dy {
.x _t _dx
.y _t _dy
}
; structure definition helper
macro struct name, [arg]
{
common
name@struct fix name
struc name arg {
}
macro struct_helper name
{
virtual at 0
name name
sizeof.#name = $ - name
name equ sizeof.#name
end virtual
}
ends fix } struct_helper name@struct
macro union [def]
{
common size@union = 0
origin@union = $
forward virtual
def
if $-origin@union > size@union
size@union = $-origin@union
end if
end virtual
common rb size@union
}
; structures used in MeOS
struc process_information
{
.cpu_usage dd ? ; +0
.window_stack_position dw ? ; +4
.window_stack_value dw ? ; +6
.not_used1 dw ? ; +8
.process_name rb 12 ; +10
.memory_start dd ? ; +22
.used_memory dd ? ; +26
.PID dd ? ; +30
.x_start dd ? ; +34
.y_start dd ? ; +38
.x_size dd ? ; +42
.y_size dd ? ; +46
.slot_state dw ? ; +50
rb (1024-52)
}
struc system_colors
{
.frame dd ?
.grab dd ?
.grab_button dd ?
.grab_button_text dd ?
.grab_text dd ?
.work dd ?
.work_button dd ?
.work_button_text dd ?
.work_text dd ?
.work_graph dd ?
}
; 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

View File

@ -3,31 +3,35 @@ section '.text' executable
public start
extrn mf_init
extrn main
;include 'debug2.inc'
__DEBUG__=0
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
include 'DEBUG-FDO.INC'
virtual at 0
db 'MENUET01' ; 1. Magic number (8 bytes)
dd 0x01 ; 2. Version of executable file
dd 0x0 ; 3. Start address
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
db 'MENUET01' ; 1. Magic number (8 bytes)
dd 0x01 ; 2. Version of executable file
dd 0x0 ; 3. Start address
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'
DEBUGF 1,'Start programm\n'
xor eax,eax
call mf_init
;DEBUGF ' path "%s"\n params "%s"\n', .path, .params
DEBUGF 1,' path "%s"\n params "%s"\n', path, params
; check for overflow
mov al, [path+buf_len-1]
or al, [params+buf_len-1]
or al, [params+buf_len-1]
jnz .crash
; check if path written by OS
mov eax, [hparams]
test eax, eax
jz .without_path
jz .without_path
mov eax, path
.without_path:
mov esi, eax
@ -35,21 +39,21 @@ start:
; retrieving parameters
mov esi, params
xor edx, edx ; dl - èä¸ò ïàðàìåòð(1) èëè ðàçäåëèòåëè(0)
; dh - ñèìâîë ñ êîòîðîãî íà÷àëñÿ ïàðàìåòð (1 êàâû÷êè, 0 îñòàëüíîå)
; dh - ñèìâîë ñ êîòîðîãî íà÷àëñÿ ïàðàìåòð (1 êàâû÷êè, 0 îñòàëüíîå)
mov ecx, 1 ; cl = 1
; ch = 0 ïðîñòî íîëü
; ch = 0 ïðîñòî íîëü
.parse:
lodsb
test al, al
jz .run
jz .run
test dl, dl
jnz .findendparam
;{åñëè áûë ðàçäåëèòåëü
;{åñëè áûë ðàçäåëèòåëü
cmp al, ' '
jz .parse ;çàãðóæåí ïðîáåë, ãðóçèì ñëåäóþùèé ñèìâîë
jz .parse ;çàãðóæåí ïðîáåë, ãðóçèì ñëåäóþùèé ñèìâîë
mov dl, cl ;íà÷èíàåòñÿ ïàðàìåòð
cmp al, '"'
jz @f ;çàãðóæåíû êàâû÷êè
jz @f ;çàãðóæåíû êàâû÷êè
mov dh, ch ;ïàðàìåòð áåç êàâû÷åê
dec esi
call push_param
@ -63,9 +67,9 @@ start:
.findendparam:
test dh, dh
jz @f ; áåç êàâû÷åê
jz @f ; áåç êàâû÷åê
cmp al, '"'
jz .clear
jz .clear
jmp .parse
@@:
cmp al, ' '
@ -78,25 +82,25 @@ start:
jmp .parse
.run:
;DEBUGF 'call main(%x, %x) with params:\n', [argc], argv
DEBUGF 1,'call main(%x, %x) with params:\n', [argc], argv
if __DEBUG__ = 1
mov ecx, [argc]
@@:
lea esi, [ecx * 4 + argv-4]
DEBUGF '0x%x) "%s"\n', cx, [esi]
DEBUGF 1,'%d) "%s"\n', cx, [esi]
loop @b
end if
push [argc]
push argv
push [argc]
call main
.exit:
;DEBUGF 'Exit from prog\n';
DEBUGF 1,'Exit from prog with code: %x\n', eax;
xor eax,eax
dec eax
int 0x40
dd -1
dd -1
.crash:
;DEBUGF 'E:buffer overflowed\n'
DEBUGF 1,'E:buffer overflowed\n'
jmp .exit
;============================
push_param:
@ -121,10 +125,10 @@ 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
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
section '.data'
include_debug_strings ; ALWAYS present in data section

View File

@ -0,0 +1,21 @@
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
/*
** atoi(s) - convert s to integer.
*/
int atoi(char *s)
{
int sign, n;
while(isspace(*s)) ++s;
sign = 1;
switch(*s) {
case '-': sign = -1;
case '+': ++s;
}
n = 0;
while(isdigit(*s)) n = 10 * n + *s++ - '0';
return (sign * n);
}

View File

@ -0,0 +1,22 @@
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
/*
** atoib(s,b) - Convert s to "unsigned" integer in base b.
** NOTE: This is a non-standard function.
*/
int atoib(char *s,int b)
{
int n, digit;
n = 0;
while(isspace(*s)) ++s;
while((digit = (127 & *s++)) >= '0') {
if(digit >= 'a') digit -= 87;
else if(digit >= 'A') digit -= 55;
else digit -= '0';
if(digit >= b) break;
n = b * n + digit;
}
return (n);
}

View File

@ -0,0 +1,19 @@
#include "ctype.h"
char __is[128] = {
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,21 @@
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
/*
** itoa(n,s) - Convert n to characters in s
*/
void itoa(int n,char* s)
{
int sign;
char *ptr;
ptr = s;
if ((sign = n) < 0) n = -n;
do {
*ptr++ = n % 10 + '0';
} while ((n = n / 10) > 0);
if (sign < 0) *ptr++ = '-';
*ptr = '\0';
reverse(s);
}

View File

@ -0,0 +1,24 @@
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
/*
** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b.
** NOTE: This is a non-standard function.
*/
void itoab(int n,char* s,int b)
{
char *ptr;
int lowbit;
ptr = s;
b >>= 1;
do {
lowbit = n & 1;
n = (n >> 1) & 32767;
*ptr = ((n % b) << 1) + lowbit;
if(*ptr < 10) *ptr += '0'; else *ptr += 55;
++ptr;
} while(n /= b);
*ptr = 0;
reverse (s);
}

View File

@ -2,12 +2,7 @@ char* strcat(char* strDest, const char* strSource)
{
char* res;
res=strDest;
while (*strDest!='\0') strDest++;
while (*strSource!='\0')
{
*strDest=*strSource;
strDest++;
strSource++;
}
while (*strDest++) ;
while (*strDest++ = *strSource++) ;
return res;
}

View File

@ -1,6 +1,6 @@
char* strchr(const char* string, int c)
{
while (*string!='\0')
while (*string)
{
if (*string==c)
return (char*)string;

View File

@ -2,13 +2,6 @@ char* strcpy(char* strDest,char* strSource)
{
char* res;
res=strDest;
while(1)
{
*strDest=*strSource;
if (*strSource=='\0')
break;
strDest++;
strSource++;
}
while(*strDest++ == strSource++) ;
return res;
}

View File

@ -2,10 +2,6 @@ int strlen(const char* string)
{
int i;
i=0;
while (*string!='\0')
{
i++;
string++;
}
while (*string!++) i++;
return i;
}

View File

@ -2,13 +2,12 @@ char* strncat(char* strDest,const char* strSource,int count)
{
char* res;
res=strDest;
while (*strDest!='\0') strDest++;
while (count>0 && *strSource!='\0')
while (*strDest++) ;
while(count-->0)
{
*strDest=*strSource;
count--;
strDest++;
strSource++;
if(*strDest++ = *strSource++) continue;
return(res);
}
*strDest = 0;
return res;
}

View File

@ -1,14 +1,12 @@
int strncmp(const char* string1, const char* string2, int count)
{
while(count>0)
while(count>0 && *string1==*string2)
{
if (*string1<*string2)
return -1;
if (*string1>*string2)
return 1;
if (*string1=='\0')
return 0;
count--;
if (*string1) return 0;
++string1;
++string2;
--count;
}
if(count) return (*string1 - *string2);
return 0;
}

View File

@ -0,0 +1,8 @@
/*
** return lower-case of c if upper-case, else c
*/
char tolower(char c)
{
if(c<='Z' && c>='A') return (c+32);
return (c);
}

View File

@ -0,0 +1,8 @@
/*
** return upper-case of c if it is lower-case, else c
*/
char toupper(char c)
{
if(c<='z' && c>='a') return (c-32);
return (c);
}