scc 0.5.3

git-svn-id: svn://kolibrios.org@718 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
jacekm 2008-02-08 11:41:42 +00:00
parent 9a8b3fd945
commit 1967c25fac
20 changed files with 27671 additions and 0 deletions

4131
programs/develop/scc/CC4.ASM Normal file

File diff suppressed because it is too large Load Diff

5066
programs/develop/scc/Cc1.asm Normal file

File diff suppressed because it is too large Load Diff

3034
programs/develop/scc/Cc2.asm Normal file

File diff suppressed because it is too large Load Diff

6740
programs/develop/scc/Cc3.asm Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,128 @@
_getarg:
PUSH EBP
MOV EBP,ESP
ADD ESP,-8
LEA EAX,[EBP+24]
MOV EBX,EAX
MOV EAX, [EBX]
MOV EBX,EAX
XOR EAX,EAX
CALL __lt
PUSH EAX
LEA EAX,[EBP+24]
MOV EBX,EAX
MOV EAX, [EBX]
PUSH EAX
LEA EAX,[EBP+12]
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
CALL __ge
POP EBX
OR EAX,EBX
OR EAX,EAX
JNE _0_3
JMP _0_2
_0_3:
LEA EAX,[EBP+20]
MOV EBX,EAX
MOV EAX, [EBX]
MOV EBX,EAX
XOR EAX,EAX
MOV [EBX],AL
MOV EAX,-1
MOV ESP,EBP
POP EBP
RET
_0_2:
LEA EAX,[EBP-8]
MOV EBX,EAX
XOR EAX,EAX
MOV [EBX],EAX
LEA EAX,[EBP-4]
PUSH EAX
LEA EAX,[EBP+8]
MOV EBX,EAX
MOV EAX, [EBX]
PUSH EAX
LEA EAX,[EBP+24]
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
SHL EAX,1
SHL EAX,1
ADD EAX,EBX
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
MOV [EBX],EAX
_0_4:
LEA EAX,[EBP-8]
MOV EBX,EAX
MOV EAX, [EBX]
PUSH EAX
LEA EAX,[EBP+16]
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
CALL __lt
OR EAX,EAX
JNE _0_6
JMP _0_5
_0_6:
LEA EAX,[EBP+20]
MOV EBX,EAX
MOV EAX, [EBX]
PUSH EAX
LEA EAX,[EBP-8]
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
ADD EAX,EBX
PUSH EAX
LEA EAX,[EBP-4]
MOV EBX,EAX
MOV EAX, [EBX]
PUSH EAX
LEA EAX,[EBP-8]
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
ADD EAX,EBX
MOV EBX,EAX
MOVSX EAX,BYTE [EBX]
POP EBX
MOV [EBX],AL
OR EAX,EAX
JE _0_8
JMP _0_7
_0_8:
JMP _0_5
_0_7:
LEA EAX,[EBP-8]
MOV EBX,EAX
MOV EAX, [EBX]
INC EAX
MOV [EBX],EAX
JMP _0_4
_0_5:
LEA EAX,[EBP+20]
MOV EBX,EAX
MOV EAX, [EBX]
PUSH EAX
LEA EAX,[EBP-8]
MOV EBX,EAX
MOV EAX, [EBX]
POP EBX
ADD EAX,EBX
MOV EBX,EAX
XOR EAX,EAX
MOV [EBX],AL
LEA EAX,[EBP-8]
MOV EBX,EAX
MOV EAX, [EBX]
MOV ESP,EBP
POP EBP
RET

View File

@ -0,0 +1,29 @@
#include <stdio.h>
/*
** Get command line argument.
** Entry: n = Number of the argument.
** s = Destination string pointer.
** size = Size of destination string.
** argc = Argument count from main().
** argv = Argument vector(s) from main().
** Returns number of characters moved on success,
** else EOF.
*/
getarg(n,s,size,argc,argv)
int n; char *s; int size,argc,argv[];
{char *str;
int i;
if(n<0 | n>=argc)
{*s=NULL;
return EOF;
}
i=0;
str=argv[n];
while(i<size)
{if((s[i]=str[i])==NULL) break;
++i;
}
s[i]=NULL;
return i;
}

View File

@ -0,0 +1,140 @@
;
; Small-C Run Time Library for Win NT
;
; Nasm version 17/Nov/98 H T Walheim
; Revised: 20/Nov/98 HTW [Bugs in switch]
;
_CCARGC:
;B+ Ellipses arguments ( ,...)
;cl - argument count
xor eax,eax
movzx eax,cl ; No sign-extension
ret
;E:.
;B+ Compare
__ult:
;B+ ???
cmp eax,ebx
ja true
xor eax,eax
ret
;E:.
__ugt:
;B+ ???
cmp eax,ebx
jb true
xor eax,eax
ret
;E:.
__ule:
;B+ ???
cmp eax,ebx
jae true
xor eax,eax
ret
;E:.
__uge:
;B+ ???
cmp eax,ebx
jbe true
xor eax,eax
ret
;E:.
__eq:
;B+ ???
cmp eax,ebx
je true
xor eax,eax
ret
;E:.
__ne:
;B+ ???
cmp eax,ebx
jne true
xor eax,eax
ret
;E:.
__lt:
;B+ ???
cmp eax,ebx
jg true
xor eax,eax
ret
;E:.
__gt:
;B+ ???
cmp eax,ebx
jl true
xor eax,eax
ret
;E:.
__le:
;B+ ???
cmp eax,ebx
jge true
xor eax,eax
ret
;E:.
__ge:
;B+ ???
cmp eax,ebx
jle true
xor eax,eax
ret
;E:.
;E:.
__lneg:
;B+ Logical Negate of Primary
or eax,eax
jnz false
true:
mov eax,1
ret
false:
xor eax,eax
ret
;E:.
__switch:
;B+ Execute "switch" statement
;eax - switch value
;[esp] - pointer to switch table
; dd addr1,value1
; ...
; dd 0
; [jmp default]
; continuation
;
; Revised: 20/Nov/98 [JECXZ needed]
pop ebx
jmp skip
back:
add ebx,8 ;next case-pair
skip:
mov ecx,[ebx] ;case-label location (adress)
jecxz default
cmp eax,[ebx+4] ;test case-value
jnz back
jmp ecx ;match -- jump to case
default:
add ebx,4
jmp ebx ;jump to default/continuation
;E:.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,440 @@
#include "stdio.h"
#include "clib.h"
/*
** Write string to standard output.
*/
puts(string) char *string;
{fputs(string,stdout);
OS_fputc('\n',stdout);
}
/*
** reverse string in place
*/
reverse(s) char *s;
{char *j; int c;
j=s+strlen(s)-1;
while(s<j)
{c=*s;
*s++ =*j;
*j-- =c;
}
}
/*
** copy t to s
*/
strcpy(s,t) char *s,*t;
{char *d;
d=s;
while(*s++ =*t++);
return (d);
}
/*
** return length of string s (fast version)
*/
strlen(s) char *s;
{char *ptr;
ptr=s;
while(*ptr)
{++ptr;
}
return (ptr-s);
#ifdef _INASM
#asm
xor al,al ; set search value to zero
mov cx,65535 ; set huge maximum
mov di,[bp+4] ; get address of s
cld ; set direction flag forward
repne scasb ; scan for zero
mov ax,65534
sub ax,cx ; calc and return length
#endasm
#endif
}
/*
** return upper-case of c if it is lower-case, else c
*/
toupper(c) int c;
{if(c<='z' && c>='a') return (c-32);
return (c);
}
/*
** atoi(s) - convert s to integer.
*/
atoi(s) 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);
}
/*
** atoib(s,b) - Convert s to "unsigned" integer in base b.
** NOTE: This is a non-standard function.
*/
atoib(s,b) 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);
}
/*
** Gets an entire string (including its newline
** terminator) or size-1 characters, whichever comes
** first. The input is terminated by a null character.
** Entry: str = Pointer to destination buffer.
** size = Size of the destination buffer.
** fd = File descriptor of pertinent file.
** Returns str on success, else NULL.
*/
fgets(str,size,fd) char *str; unsigned size,fd;
{return (_gets(str,size,fd,1));
}
/*
** Gets an entire string from stdin (excluding its newline
** terminator) or size-1 characters, whichever comes
** first. The input is terminated by a null character.
** The user buffer must be large enough to hold the data.
** Entry: str = Pointer to destination buffer.
** Returns str on success, else NULL.
*/
gets(str) char *str;
{return (_gets(str,32767,stdin,0));
}
_gets(str,size,fd,nl) char *str; unsigned size,fd,nl;
{int backup; char *next;
next=str;
while(--size>0)
{switch (*next=fgetc(fd))
{case EOF:
*next=NULL;
if(next==str) return (NULL);
return (str);
case '\n':
*(next+nl)=NULL;
return (str);
case RUB: /* \b */
if(next>str) backup=1;
else backup=0;
goto backout;
case WIPE: /* \r */
backup=next-str;
backout:
if(0/*iscons(fd)*/)
{++size;
while(backup--)
{fputs("\b \b",stderr);
--next;++size;
}
continue;
}
default:
++next;
}
}
*next = NULL;
return (str);
}
/*
** fprintf(fd, ctlstring, arg, arg, ...) - Formatted print.
** Operates as described by Kernighan & Ritchie.
** b, c, d, o, s, u, and x specifications are supported.
** Note: b (binary) is a non-standard extension.
*/
fprintf(argc) int argc;
{int *nxtarg;
nxtarg=CCARGC()+&argc;
return(_print(*(--nxtarg),--nxtarg));
}
/*
** printf(ctlstring, arg, arg, ...) - Formatted print.
** Operates as described by Kernighan & Ritchie.
** b, c, d, o, s, u, and x specifications are supported.
** Note: b (binary) is a non-standard extension.
*/
printf(argc) int argc;
{return(_print(stdout,CCARGC()+&argc-1));
}
/*
** _print(fd, ctlstring, arg, arg, ...)
** Called by fprintf() and printf().
*/
_print(fd,nxtarg) int fd,*nxtarg;
{int arg,left,pad,cc,len,maxchr,width;
char *ctl,*sptr,str[17];
cc=0;
ctl=*nxtarg--;
while(*ctl)
{if(*ctl!='%') {OS_fputc(*ctl++,fd); ++cc; continue;}
else ++ctl;
if(*ctl=='%') {OS_fputc(*ctl++,fd); ++cc; continue;}
if(*ctl=='-') {left=1; ++ctl;} else left=0;
if(*ctl=='0') pad='0';
else pad=' ';
if(isdigit(*ctl))
{width=atoi(ctl++);
while(isdigit(*ctl)) ++ctl;
}else width=0;
if(*ctl=='.')
{maxchr=atoi(++ctl);
while(isdigit(*ctl)) ++ctl;
}else maxchr=0;
arg=*nxtarg--;
sptr=str;
switch(*ctl++)
{case 'c': str[0]=arg; str[1]=NULL; break;
case 's': sptr=arg; break;
case 'd': itoa(arg,str); break;
case 'b': itoab(arg,str,2); break;
case 'o': itoab(arg,str,8); break;
case 'u': itoab(arg,str,10); break;
case 'x': itoab(arg,str,16); break;
default: return (cc);
}
len=strlen(sptr);
if(maxchr && maxchr<len) len=maxchr;
if(width>len) width=width-len; else width=0;
if(!left) while(width--) {OS_fputc(pad,fd); ++cc;}
while(len--) {OS_fputc(*sptr++,fd); ++cc;}
if(left) while(width--) {OS_fputc(pad,fd); ++cc;}
}
return (cc);
}
/*
** Write a string to fd.
** Entry: string = Pointer to null-terminated string.
** fd = File descriptor of pertinent file.
*/
fputs(string,fd) char *string; int fd;
{while(*string)
OS_fputc(*string++,fd);
}
/*
** 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
int _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
};
isalnum (c) int c; {return (_is[c] & ALNUM );} /* 'a'-'z', 'A'-'Z', '0'-'9' */
isalpha (c) int c; {return (_is[c] & ALPHA );} /* 'a'-'z', 'A'-'Z' */
iscntrl (c) int c; {return (_is[c] & CNTRL );} /* 0-31, 127 */
isdigit (c) int c; {return (_is[c] & DIGIT );} /* '0'-'9' */
isgraph (c) int c; {return (_is[c] & GRAPH );} /* '!'-'~' */
islower (c) int c; {return (_is[c] & LOWER );} /* 'a'-'z' */
isprint (c) int c; {return (_is[c] & PRINT );} /* ' '-'~' */
ispunct (c) int c; {return (_is[c] & PUNCT );} /* !alnum && !cntrl && !space */
isspace (c) int c; {return (_is[c] & BLANK );} /* HT, LF, VT, FF, CR, ' ' */
isupper (c) int c; {return (_is[c] & UPPER );} /* 'A'-'Z' */
isxdigit(c) int c; {return (_is[c] & XDIGIT);} /* '0'-'9', 'a'-'f', 'A'-'F' */
/*
** itoa(n,s) - Convert n to characters in s
*/
itoa(n,s) char *s; int n;
{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);
}
/*
** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b.
** NOTE: This is a non-standard function.
*/
itoab(n,s,b) 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);
}
/*
** itod -- convert nbr to signed decimal string of width sz
** right adjusted, blank filled; returns str
**
** if sz > 0 terminate with null byte
** if sz = 0 find end of string
** if sz < 0 use last byte for data
*/
itod(nbr,str,sz) int nbr; char str[]; int sz;
{char sgn;
if(nbr<0) {nbr=-nbr; sgn='-';}
else sgn=' ';
if(sz>0) str[--sz]=NULL;
else if(sz<0) sz=-sz;
else while(str[sz]!=NULL) ++sz;
while(sz)
{str[--sz]=(nbr%10+'0');
if((nbr=nbr/10)==0) break;
}
if(sz) str[--sz]=sgn;
while(sz>0) str[--sz]=' ';
return str;
}
/*
** itoo -- converts nbr to octal string of length sz
** right adjusted and blank filled, returns str
**
** if sz > 0 terminate with null byte
** if sz = 0 find end of string
** if sz < 0 use last byte for data
*/
itoo(nbr,str,sz) int nbr; char str[]; int sz;
{int digit;
if(sz>0) str[--sz]=0;
else if(sz<0) sz=-sz;
else while(str[sz]!=0) ++sz;
while(sz)
{digit=nbr&7;nbr=(nbr>>3)&8191;
str[--sz]=digit+48;
if(nbr==0) break;
}
while(sz) str[--sz]=' ';
return str;
}
/*
** itou -- convert nbr to unsigned decimal string of width sz
** right adjusted, blank filled; returns str
**
** if sz > 0 terminate with null byte
** if sz = 0 find end of string
** if sz < 0 use last byte for data
*/
itou(nbr,str,sz) int nbr; char str[]; int sz;
{int lowbit;
if(sz>0) str[--sz]=NULL;
else if(sz<0) sz=-sz;
else while(str[sz]!=NULL) ++sz;
while(sz)
{lowbit=nbr&1;
nbr=(nbr>>1)&32767; /* divide by 2 */
str[--sz]=((nbr%5)<<1)+lowbit+'0';
if((nbr=nbr/5)==0) break;
}
while(sz) str[--sz]=' ';
return str;
}
/*
** itox -- converts nbr to hex string of length sz
** right adjusted and blank filled, returns str
**
** if sz > 0 terminate with null byte
** if sz = 0 find end of string
** if sz < 0 use last byte for data
*/
itox(nbr,str,sz) int nbr; char str[]; int sz;
{int digit,offset;
if(sz>0) str[--sz]=0;
else if(sz<0) sz=-sz;
else while(str[sz]!=0) ++sz;
while(sz)
{digit=nbr&15;
nbr=nbr/16;
/*
nbr=(nbr>>4)&4095; // 268435455; // 0xFFFFFFF
*/
if(digit<10) offset=48;
else offset=55;
str[--sz]=digit+offset;
if(nbr==0) break;
}
while(sz) str[--sz]=' ';
return str;
}

View File

@ -0,0 +1,268 @@
; 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
macro code
{
__start:
}
CODE fix code
macro data
{
__data:
}
DATA fix data
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
}
UDATA fix udata
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_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
}
; strings
macro sz name,[data] { ; from MFAR [mike.dld]
common
if used name
label name
end if
forward
if used name
db data
end if
common
if used name
.size = $-name
end if
}
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
common
if used name
label name
end if
forward
if (used name)&(lang eq lng)
db data
end if
common
if used name
.size = $-name
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
}
; language for programs
lang fix ru ; ru en fr ge fi
; 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
}
macro struct name
{
virtual at 0
name name
sizeof.#name = $ - name
end virtual
}
; 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)
}
struct process_information
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 ?
}
struct system_colors
; 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

@ -0,0 +1,6 @@
/*
** NOTICE.H -- Small C Signon Notice.
*/
#define VERSION "Small C 386/NT, Version 3.1, Revision Level 1\n"
#define CRIGHT1 "Copyright 1982-1998 J. E. Hendrix H T Walheim\n"
#define CRIGHT2 "2008 - port to KolibriOS (jacekm.pl@gmail.com)\n\n"

View File

@ -0,0 +1,681 @@
include "macros.inc"
;
; OS function implementation
; SmallC for KolibriOS
;
;B+ General definitions
;B+ File defs
;const
;param
BAD equ -1
files equ 100
save_buffer equ 0x20000 ;32
save_buffer_w equ 0x400000 ;32
save_file_name equ 0x20000
;system
EOF equ -1
;memory
fileinfo equ I_END
start_data equ (fileinfo+16384)
;
mem_heap equ 0x100000
;
g_handle equ 0x300000
;dword - pointer - relative to file
;dword - begin of file
;dword - file size
;dword - 0/1 <=> read/write
;E:.
;E:.
init_osfunc:
;B+ Init OS functions
;B+ Clear file handles
mov edi,g_handle
mov ecx,files
shl ecx,2 ;*4
xor eax,eax
cld
rep stosd
;E:.
ret
;E:.
;B+ Main OS functions
ppp dd 70
_OS_fopen:
;B+ Implement "fopen"
;esp+4 - mode
;esp+8 - file name
; mov eax,-1
; int 0x40
; mov ebx,[esp+8];
; push dword 10
; push dword [ppp]
; push ebx
; push dword 12
; call _outstrg
; add esp,4*4
; add [ppp],10
; cmp byte [ebx+8],0
; jne .l
; mov byte [ebx+8],'?'
;.l:
; cmp [ppp],80
; je .l
mov ecx , [esp+4] ; file mode
mov [file_mode],ecx
;B+ Copy file name
mov esi,[esp+8]
mov edi,[p_filename]
mov ecx,12
.next_copy:
lodsb
;fill name (space)
or al,al
jz .fill_space
;set upper case
cmp al,'a'
jb .good_char
cmp al,'z'
ja .good_char
add al,'A'-'a'
.good_char:
stosb
dec ecx
jnz .next_copy
.fill_space:
mov al,' '
cld
rep stosb
mov eax,[file_mode]
cmp byte [eax],'w'
jne .no_wri
;B+ Copy file name
mov esi,[esp+8]
mov edi,[w_file_name]
mov ecx,12
.next_copy2:
lodsb
;fill name (space)
or al,al
jz .fill_space2
;set upper case
cmp al,'a'
jb .good_char2
cmp al,'z'
ja .good_char2
add al,'A'-'a'
.good_char2:
stosb
dec ecx
jnz .next_copy2
.fill_space2:
mov al,' '
cld
rep stosb
.no_wri:
;E:.
;B+ Find file handle
mov eax,g_handle
.new_handle:
cmp dword [eax+4],0
je .find_place
add eax,16
cmp eax,g_handle+files*16-16
jne .new_handle
xor eax,eax ; no free handle
ret
.find_place:
; TMP: mov eax,[.ccc]
; TMP: add [.ccc],16
;E:.
push eax
;B+ Test open mode
mov eax,[esp+4+4]
cmp byte [eax],'r'
je .open_read
cmp byte [eax],'w'
je .open_write
;bad mode
add esp,4
mov eax,eax ; invalid open mode
ret
;E:.
; TMP:.ccc dd g_handle
.open_read:
;B+ Open for read
;B+ Read file
;Wait to read correct
mov ebx,100
mov eax,5
int 0x40
mov eax,[g_fileend]
mov dword [file_parameters+2*4],2000 ;read all
mov dword [file_parameters+3*4],eax
mov dword [file_parameters],0
mov ebx,file_parameters
mov eax,58
int 0x40
;E:.
;B+ TEST FILE FOUND
or eax,eax
jz .file_found
cmp eax,5
je .file_found
; mov ecx,eax ; eax
; mov ebx,8 shl 16 + 0x0100
; mov edx,100 shl 16 + 120
; mov esi,0xffffff
; mov eax,47
; int 0x40
;file not found - return 0
add esp,4
xor eax,eax
ret
.file_found:
;E:.
pop eax
push ebx
xchg eax,ebx
;B+ Fill file handle
;save current pointer
xor eax,eax
mov [ebx],eax
;save file begin
mov eax,[g_fileend]
mov [ebx+4],eax
;save file size
pop eax
mov [ebx+8],eax
;reserve file zone
add eax,7
and eax,not 7
add [g_fileend],eax
;save file mode
mov eax,0 ;read
mov [ebx+12],eax
;E:.
xchg eax,ebx ;return pointer place
ret
;E:.
.open_write:
;B+ Open for write
;B+ Reserve filename
; p_filename -> w_file_name
;pusha
; mov eax, w_file_name
; mov ebx, [p_filename]
;.ncpy:
; mov ch, byte [ebx]
; cmp ch, 0
; je .ecpy
; mov [eax], ch
; inc dword [eax]
; inc dword [ebx]
;jmp .ncpy
;
;.ecpy:
;
;popa
mov [save_buffer_p], save_buffer_w
mov esi,[p_filename]
mov edi,[g_fileend]
mov ecx,12
cld
rep movsb
add [g_fileend],16
;E:.
pop ebx
;B+ Fill file handle
;save begin pointer
xor eax,eax
mov [ebx],eax
;save file begin
mov eax,[g_fileend]
mov [ebx+4],eax
;save file zone
mov dword [ebx+8],save_buffer
;reserve file zone
add [g_fileend],save_buffer
;save file mode
mov eax,1 ;write
mov [ebx+12],eax
;E:.
xchg eax,ebx ;return pointer place
ret
;E:.
;E:.
_OS_fclos:
;B+ Close file
;esp+4 - file handle
;B+ Test write mode - save file
mov eax,[esp+4]
mov eax,[eax+12]
cmp eax,1
;E:.
jne .no_write
mov eax, [esp+4]
mov ecx, [eax]
mov ebx, [eax+8]
mov ebx, [save_buffer_p]
sub ebx, save_buffer_w
; ebx = number of read bytes = file size
; save loaded file
mov [dest_info.bytes],ebx ; file size in bytes
mov [dest_info.bytes+4], save_buffer_w
;mov eax, [p_filename];[w_file_name]
;mov [destination],eax
mov eax,70
mov ebx,dest_info
mcall
; check if 58 function failed
test eax,eax
je .ok_write
add eax,7 ; error number += 7
cmp eax,6+7
jna .copy_error
mov eax,7+7
jmp .copy_error
.copy_error:
.ok_write:
;E:.
jmp .read
.no_write:
;B+ Test read mode - if no error end
cmp eax,0
je .read
mov eax,BAD
ret
;E:.
.read:
;B+ Relace memory
;find file size
mov eax,[esp+4]
mov ecx,[eax+8]
add ecx,7
and ecx,not 7
push ecx
;mov memory
mov esi,[eax+4]
mov edi,esi
add esi,ecx
mov ecx,[g_fileend]
sub ecx,edi
jz .is_last
shr ecx,2
inc ecx ;not neccessery
cld
rep movsd
;update gl. memory
.is_last:
pop ecx
sub dword [g_fileend],ecx
;update file pointers
mov edx,ecx
mov ecx,[eax+4]
mov eax,g_handle
.new_handle1:
mov ebx,[eax+4]
cmp ebx,ecx
jbe .no_update
sub ebx,edx
mov [eax+4],ebx
.no_update:
add eax,16
cmp eax,g_handle+files*16
jne .new_handle1
;clear handle
mov edi,[esp+4]
xor eax,eax
cld
stosd
stosd
stosd
stosd
;E:.
ret
;E:.
_OS_fgetc:
;B+ Load char from file
;esp+4 - input file
mov eax,[esp+4]
mov ebx,[eax]
cmp ebx,[eax+8]
je .eof
inc dword [eax]
add ebx,[eax+4]
movzx eax,byte [ebx]
ret
.eof:
mov eax,EOF
ret
;E:.
;rrr db 'g',0
_OS_fputc:
;B+ Save char to file
;esp+4 - output file
;esp+8 - char to write
;push dword '<'
;mov cl,1
;push dword 0
;call test_outch
;add esp,8
;B+ Temp - write direct.
cmp dword [esp+4],__iob
jne .real_write0
jmp _OS_exit
.real_write0:
cmp dword [esp+4],__iob+32
jne .real_write1
mov [print_textcolor],0x00ffff
jmp test_outch
.real_write1:
cmp dword [esp+4],__iob+64
jne .real_write2
mov [print_textcolor],0x77ffff
jmp test_outch
.real_write2:
;E:.
mov ebx,[save_buffer_p]
mov eax,[esp+8]
mov [ebx],eax
inc dword [save_buffer_p]
ret
;push dword '<'
;mov cl,1
;push dword 0
;call test_outch
;add esp,8
mov eax,[esp+4]
mov ebx,[eax]
push ebx
cmp ebx,[eax+8]
jne .write_normal
;B+ Alloc save_buffer bytes
;mov memory
mov ebx,[esp+4+4]
mov esi,[g_fileend]
mov edi,esi
add edi,save_buffer-4
mov ecx,esi
sub ecx,[ebx+4]
sub ecx,[ebx+8]
shr ecx,2
jz .is_last
sub esi,4
std
rep movsd
.is_last:
;expand file size
add dword [eax+8],save_buffer
;update file pointers
mov ebx,g_handle
.new_handle:
mov ecx,[ebx+4]
cmp [eax+4],ecx
jae .no_update
add dword [ebx+4],save_buffer
.no_update:
add ebx,16
cmp ebx,g_handle+files*16-16
jne .new_handle
;E:.
.write_normal:
pop ebx
inc dword [eax]
add ebx,[eax+4]
mov cl,[esp+8]
mov byte [ebx],cl
;sub [test_outch.x_coord],2
;
;push dword '>'
;mov cl,1
;push dword 0
;call test_outch
;add esp,8
;
;sub [test_outch.x_coord],6
xor eax,eax
ret
;E:.
_OS_callo:
;B+ Alloc memory
;find all size
mov eax,[esp+4]
mov ebx,[esp+8]
mul ebx
push eax
;clear memory
mov edi,[.mem_p]
xor eax,eax
mov ecx,[esp]
cld
rep stosb
;update new memory pointer
pop ebx
push dword [.mem_p]
add ebx,7
and ebx,not 7
add [.mem_p],ebx
;return value
pop eax
ret
.mem_p dd mem_heap
;E:.
_OS_exit:
;B+ Exit program
; ;TMP
; mov eax,-1
; int 0x40
mov esp,[exit_esp]
sub esp,4
ret
;E:.
;E:.
;B+ Test procedures
;B+ Definitions
LEFTMARGIN equ 11
BEGIN_CHARS equ 20
NL equ 10
;E:.
print_textcolor dd 0x00ffff
_file_beg:
;B+ Show begin of file - test fopen
;esp+4 - file handle (descriptor)
mov eax,[esp+4]
mov ebx,10 shl 16 + 30
mov ecx,[print_textcolor]
mov edx,[eax+4]
mov esi,BEGIN_CHARS
mov eax,4
int 0x40
ret
;E:.
_outstrg:
;B+ Draw black text - test function call
;esp+4*4 - x
;esp+4*3 - y
;esp+4*2 - *c
;esp+4*1 - len
mov ebx,[esp+4*4]
shl ebx,16
mov bx,[esp+4*3]
mov ecx,[print_textcolor]
mov edx,[esp+4*2]
mov esi,[esp+4]
mov eax,4
int 0x40
ret
;E:.
test_outch:
;B+ Draw one char - use as _OS_fputc, to test printf(...)
;esp+8 - char to write
;this is test! \b \r - not nesessary
mov al,[esp+8]
cmp al,NL
jne .no_newline
add [.y_coord],10
mov [.x_coord],LEFTMARGIN
ret
.no_newline:
mov ebx,[.x_coord]
shl ebx,16
mov bx,word [.y_coord]
mov ecx,[print_textcolor]
mov [.out_char],al
mov edx,.out_char
mov esi,1
mov eax,4
int 0x40
add [.x_coord],6
;mov eax,5
;mov ebx,5
;int 0x40
ret
.x_coord dd LEFTMARGIN
.y_coord dd 60
.out_char db 0
;E:.
;E:.
;B+ Data section
;B+ Memory managment
g_fileend dd g_handle+files*4*4 ;from 2MB+100*4*4
;w_buff dd
;E:.
save_buffer_p dd save_buffer_w
;B+ File parameters
file_parameters:
dd 0x0 ; mode
dd 0x0 ; first block
dd 1000 ; block read
dd -1 ; return place
dd fileinfo ; work area
filepath: times 100 db 0
file_mode dd 0 ;file mode
dest_info: ; DESTINATION FILEINFO
dd 2
dd 0
dd 0
.bytes dd ?
dd save_buffer
db 0
destination:
dd save_file_name
;db "EXAMPLE.ASM",0
w_file_name dd save_file_name
p_filename dd 0x0
;E:.
;E:.
;TO DO
mov eax,-1
int 0x40
;TO DO

View File

@ -0,0 +1,18 @@
##############################
# SCC (simple c compiler)
# port of CCOMP to KolibriOS
#
######
# contact: jacekm.pl@gmail.com
##############################
KNOWN BUGS:
* only directiory /rd/1/ works
HISTORY:
* 0.5.3:
- output dir fixed
* 0.5.2:
- static output file
* 0.5.1:
- first realase

View File

@ -0,0 +1,392 @@
;
; Port to KolibliOS
; (jacekm.pl@gmail.com)
;
;B+ System header
use32
org 0x0
db 'MENUET01'
dd 0x01
dd START
dd I_END
dd 0x500000
dd 0x7fff0
dd 0x0,0x0
;E:.
;B+ Include C files
; Compiler tools
include "INTRINS.ASM"
; C Library ("stdio.asm")
include "LIBSTD.ASM"
; MenuetOS implement
include "OSFUNC.ASM"
_fopen equ _OS_fopen
_fputc equ _OS_fputc
_fgetc equ _OS_fgetc
_fclose equ _OS_fclos
;Main program (compiled from C)
include "GETARG.ASM"
include "CC1.ASM"
include "CC2.ASM"
include "CC3.ASM"
include "CC4.ASM"
;E:.
START:
;B+ Main cycle
call draw_window
still:
mov eax,10
int 0x40
still1:
cmp eax,1
je red
cmp eax,2
je key
cmp eax,3
je button
jmp still
red:
call draw_window
jmp still
key:
mov eax,2
int 0x40
jmp still
button:
mov eax,17
int 0x40
cmp ah,1
jne .noclose
mov eax,-1
int 0x40
.noclose:
cmp ah,2
jne .no_run
; call begin_osfunc
;B+ Copy file path
mov esi,inp_path
mov edi,filepath
mov ecx,[p_len]
push ecx
cld
rep movsb
pop ecx
add ecx,filepath
mov [p_filename],ecx
;E:.
;B+ Clear word area
mov ebx,10 shl 16 + 280
mov ecx,60 shl 16 + 250
mov edx,0x303030
mov eax,13
int 0x40
;E:.
;B+ Init parameters
mov ecx,_input
sub ecx,_nogo
mov edi,_nogo
xor eax,eax
cld
rep stosb
mov [_input],-1
mov [_input2],-1
mov [_usexpr],1
mov [_ccode],1
mov [_quote],34
mov [test_outch.y_coord],60
;E:.
call init_osfunc
push dword 4
push args
;B+ Save exit ESP
mov [exit_esp],esp
;E:.
call _main
add esp,8
; call end_osfunc
.no_run:
cmp ah,3
jne .no_path
mov eax,inp_path
mov bx,27
call read_string
mov edx,[r_pos]
mov [p_len],edx
;
cmp ah,10
je still
jmp still1
.no_path:
cmp ah,4
jne .no_file
mov eax,inp_file
mov bx,42
call read_string
mov edx,[r_pos]
mov [f_len],edx
;
cmp ah,10
je still
jmp still1
.no_file:
jmp still
;E:.
read_string:
;B+ Read string
mov [c_place],eax
mov [r_pos],0
mov [rel_x],60
mov [rel_y],bx
mov ebx,60
shl ebx,16
mov bx,6*26+1
movzx ecx,[rel_y]
shl ecx,16
mov cx,10
mov edx,0x000000
mov eax,13
int 0x40
add ecx,11 shl 16
mov cx,2
mov edx,0x999999
int 0x40
.next:
mov ebx,[rel_x]
shl ebx,16
mov bx,7
movzx ecx,[rel_y]
shl ecx,16
mov cx,10
mov edx,0x000000
mov eax,13
int 0x40
mov ebx,[c_place]
mov byte [ebx],0
mov eax,10
int 0x40
cmp eax,2
je .key
jmp .to_ret
.key:
mov eax,2
int 0x40
cmp ah,13
jne .no_enter
jmp .to_ret
.no_enter:
cmp ah,8
jne .no_back
cmp [r_pos],0
je .next
dec [r_pos]
dec [c_place]
sub [rel_x],6
jmp .next
.no_back:
cmp [r_pos],25
je .next
cmp ah,'a'
jb .no_sm_l
cmp ah,'z'
ja .no_sm_l
add ah,'A'-'a'
.no_sm_l:
mov byte [ebx],ah
mov [char],ah
inc [c_place]
inc [r_pos]
mov ebx,[rel_x]
inc ebx
shl ebx,16
mov bx,[rel_y]
inc bx
mov ecx,0x00ffff
mov edx,char
mov esi,1
mov eax,4
int 0x40
add [rel_x],6
jmp .next
.to_ret:
push eax
mov ebx,60
shl ebx,16
mov bx,6*26+1
movzx ecx,[rel_y]
add ecx,11
shl ecx,16
mov cx,2
mov edx,0x000000
mov eax,13
int 0x40
pop eax
ret
rel_x dd 60
rel_y dw 0x0
c_place dd 0x0
r_pos dd 0x0
char db '?'
;E:.
draw_window:
;B+ Draw window
mov eax,12
mov ebx,1
int 0x40
mov ebx,100*65536+300
mov ecx,100*65536+320
mov edx,0x035555DD
mov esi,0x805080d0
mov edi,0x005080d0
mov eax,0
int 0x40
mov ebx,8*65536+8
mov ecx,0x10ddeeff
mov edx,caption
mov esi,caption_end-caption
mov eax,4
int 0x40
;mov ebx,(300-19)*65536+12
;mov ecx,5*65536+12
;mov edx,1
;mov esi,0x6688dd
;mov eax,8
;int 0x40
;B+ Hot buttons
mov ebx,220 shl 16 + 70
mov ecx,25 shl 16 + 29
mov edx,2 ; compile
mov esi,0x6688dd
mov eax,8
int 0x40
mov ebx,10 shl 16 + 47
mov ecx,26 shl 16 + 12
mov edx,3 ; path
mov esi,0x6688dd
mov eax,8
int 0x40
mov ebx,10 shl 16 + 47
mov ecx,41 shl 16 + 12
mov edx,4 ; file name
mov esi,0x6688dd
mov eax,8
int 0x40
;E:.
;B+ Text in buttons
mov ebx,231 shl 16 + 36
mov ecx,0x10ffffff
mov edx,txt_compile
mov esi,txt_compile_end-txt_compile
mov eax,4
int 0x40
mov ebx,14 shl 16 + 28
mov ecx,0xffffff
mov edx,txt_path
mov esi,txt_path_end-txt_path
int 0x40
mov ebx,14 shl 16 + 43
mov edx,txt_file
mov esi,txt_file_end-txt_file
int 0x40
;E:.
;B+ Draw path / file name
mov ebx,61 shl 16 + 28
mov ecx,0x00ffff
mov edx,inp_path
mov esi,[p_len]
mov eax,4
int 0x40
mov ebx,61 shl 16 + 43
mov ecx,0x00ffff
mov edx,inp_file
mov esi,[f_len]
mov eax,4
int 0x40
;E:.
mov eax,12
mov ebx,2
int 0x40
ret
;E:.
;B+ Data area
;B+ Interface
inp_path: times 100 db '/RD/1/',0
p_len dd 6
inp_file: times 100 db 'EXAMPLE',0
f_len dd 7
txt_compile db 'Compile'
txt_compile_end:
txt_path db 'Path ->'
txt_path_end:
txt_file db 'File ->'
txt_file_end:
;E:.
;B+ Main arguments
args dd arg_str0,inp_file,arg_str2,arg_str3,arg_str4
arg_str0 db 'CC',0
arg_str1 db 'prog',0
arg_str2 db '-m',0
arg_str3 db '-a',0
arg_str4 db '-p',0
;E:.
;B+ System parameters
exit_esp dd 0x0
;E:.
caption db 'Small C compiler for KolibriOS v 0.5.3'
caption_end:
times 8-($ mod 8) db 0
;E:.
I_END:

View File

@ -0,0 +1,33 @@
/*
** STDIO.H -- Standard Small C Definitions.
*/
extern char _iob[];
#define exit OS_exit
#define fopen OS_fopen
#define fgetc OS_fgetc
#define fputc OS_fputc
#define fclose OS_fclose
#define calloc OS_calloc // stdlib.h
#define SIZEOF_FILE 32 // sizeof (FILE)
#define stdin (&_iob[0])
#define stdout (&_iob[1*SIZEOF_FILE])
#define stderr (&_iob[2*SIZEOF_FILE])
#define stdaux 3 /* file descriptor for standard auxiliary port */
#define stdprn 4 /* file descriptor for standard printer */
#define FILE char /* supports "FILE *fp;" declarations */
#define ERR (-2) /* return value for errors */
#define EOF (-1) /* return value for end-of-file */
#define YES 1 /* true */
#define NO 0 /* false */
#define NULL 0 /* zero */
#define CR 13 /* ASCII carriage return */
#define LF 10 /* ASCII line feed */
#define BELL 7 /* ASCII bell */
#define SPACE ' ' /* ASCII space */
#define NEWLINE LF /* Small C newline character */

320
programs/develop/scc/cc.h Normal file
View File

@ -0,0 +1,320 @@
/*
** CC.H -- Symbol Definitions for Small-C compiler.
*/
#ifdef _MSC_VER
#define YES 1 /* true */
#define NO 0 /* false */
#define CR 13 /* ASCII carriage return */
#define LF 10 /* ASCII line feed */
#define BELL 7 /* ASCII bell */
#define SPACE ' ' /* ASCII space */
#define NEWLINE LF /* Small C newline character */
#endif
/*
** size of 'int'
*/
#define INT32 /* if #defined int = 32 bits, else 16 */
/*
** ALIGNMENT
*/
#define ALIGN 4
/*
** machine dependent parameters
*/
#define BPD 4 /* bytes per dword */
#define LBPD 2 /* log2(BPD) */
#define BPW 2 /* bytes per word */
#define LBPW 1 /* log2(BPW) */
#define SBPC 1 /* stack bytes per character */
#define ERRCODE 7 /* op sys return code */
#define INTSIZE 4
/*
** symbol table format
*/
#define IDENT 0
#define TYPE 1
#define CLASS 2
#define SIZE 3
#define OFFSET 5+2
#define NAME (7+4)
#define SYMAVG (12+4)
#define SYMMAX (16+4)
/*
** symbol table parameters
*/
#define NUMLOCS 25
#define STARTLOC symtab
#define ENDLOC (symtab+NUMLOCS*SYMAVG)
#define NUMGLBS 200
#define STARTGLB ENDLOC
#define ENDGLB (ENDLOC+(NUMGLBS-1)*SYMMAX)
#define SYMTBSZ /*3050*/ (NUMLOCS*SYMAVG + NUMGLBS*SYMMAX)
/*
** system wide name size (for symbols)
*/
#define NAMESIZE 9
#define NAMEMAX 8
/*
** values for "IDENT"
*/
#define LABEL 0
#define VARIABLE 1
#define ARRAY 2
#define POINTER 3
#define FUNCTION 4
#define PTRSIZE INTSIZE /* Size of pointer (must match an int!) */
/*
** values for "TYPE"
** high order 14 bits give length of object
** low order 2 bits make type unique within length
*/
/* LABEL 0 */
#define CHR ( 1 << 2)
#define SHORT (BPW << 2)
#define INT (INTSIZE << 2)
#define UCHR (( 1 << 2) + 1)
#define USHORT ((BPW << 2) + 1)
#define UINT ((INTSIZE << 2) + 1)
#define UNSIGNED 1
/*
** values for "CLASS"
*/
/* LABEL 0 */
#define AUTOMATIC 1
#define STATIC 2
#define EXTERNAL 3
#define AUTOEXT 4
/*
** segment types
*/
#define DATASEG 1
#define CODESEG 2
/*
** "switch" table
*/
#define SWSIZ (2*BPW)
#define SWTABSZ (90*SWSIZ)
/*
** "while" queue
*/
#define WQTABSZ 30
#define WQSIZ 3
#define WQMAX (wq+WQTABSZ-WQSIZ)
/*
** field offsets in "while" queue
*/
#define WQSP 0
#define WQLOOP 1
#define WQEXIT 2
/*
** literal pool
*/
#define LITABSZ 3000
#define LITMAX (LITABSZ-1)
/*
** input line
*/
#define LINEMAX 127
#define LINESIZE 128
/*
** entries in staging buffer
*/
#define STAGESIZE 200
/*
** macro (#define) pool
*/
#define MACNBR 300
#define MACNSIZE (MACNBR*(NAMESIZE+2))
#define MACNEND (macn+MACNSIZE)
#define MACQSIZE (MACNBR*7)
#define MACMAX (MACQSIZE-1)
/*
** statement types
*/
#define STIF 1
#define STWHILE 2
#define STRETURN 3
#define STBREAK 4
#define STCONT 5
#define STASM 6
#define STEXPR 7
#define STDO 8
#define STFOR 9
#define STSWITCH 10
#define STCASE 11
#define STDEF 12
#define STGOTO 13
#define STLABEL 14
/*
** p-code symbols
**
** legend:
** 1 = primary register (pr in comments)
** 2 = secondary register (sr in comments)
** b = byte
** f = jump on false condition
** l = current literal pool label number
** m = memory reference by label
** n = numeric constant
** p = indirect reference thru pointer in sr
** r = repeated r times
** s = stack frame reference
** u = unsigned
** w = word
** _ (tail) = another p-code completes this one
*/
/* compiler-generated */
#define ADD12 1 /* add sr to pr */
#define ADDSP 2 /* add to stack pointer */
#define AND12 3 /* AND sr to pr */
#define ANEG1 4 /* arith negate pr */
#define ARGCNTn 5 /* pass arg count to function */
#define ASL12 6 /* arith shift left sr by pr into pr */
#define ASR12 7 /* arith shift right sr by pr into pr */
#define CALL1 8 /* call function thru pr */
#define CALLm 9 /* call function directly */
#define BYTE_ 10 /* define bytes (part 1) */
#define BYTEn 11 /* define byte of value n */
#define BYTEr0 12 /* define r bytes of value 0 */
#define COM1 13 /* ones complement pr */
#define DBL1 14 /* double pr */
#define DBL2 15 /* double sr */
#define DIV12 16 /* div pr by sr */
#define DIV12u 17 /* div pr by sr unsigned */
#define DWORD_ 111 /* define dword (part 1) */
#define DWORDn 112 /* define dword of value n */
#define DWORDr0 113 /* define r dwords of value 0 */
#define ENTER 18 /* set stack frame on function entry */
#define EQ10f 19 /* jump if (pr == 0) is false */
#define EQ12 20 /* set pr TRUE if (sr == pr) */
#define GE10f 21 /* jump if (pr >= 0) is false */
#define GE12 22 /* set pr TRUE if (sr >= pr) */
#define GE12u 23 /* set pr TRUE if (sr >= pr) unsigned */
#define POINT1l 24 /* point pr to function's literal pool */
#define POINT1m 25 /* point pr to mem item thru label */
#define GETb1m 26 /* get byte into pr from mem thru label */
#define GETb1mu 27 /* get unsigned byte into pr from mem thru label */
#define GETb1p 28 /* get byte into pr from mem thru sr ptr */
#define GETb1pu 29 /* get unsigned byte into pr from mem thru sr ptr */
#define GETd1m 107 /* get dword into pr from mem thru label */
#define GETd1n 108 /* get dword of value n into pr */
#define GETd1p 109 /* get dword into pr from mem thru sr ptr */
#define GETd2n 110 /* get word of value n into sr */
#define GETw1m 30 /* get word into pr from mem thru label */
#define GETw1n 31 /* get word of value n into pr */
#define GETw1p 32 /* get word into pr from mem thru sr ptr */
#define GETw2n 33 /* get word of value n into sr */
#define GT10f 34 /* jump if (pr > 0) is false */
#define GT12 35 /* set pr TRUE if (sr > pr) */
#define GT12u 36 /* set pr TRUE if (sr > pr) unsigned */
#define WORD_ 37 /* define word (part 1) */
#define WORDn 38 /* define word of value n */
#define WORDr0 39 /* define r words of value 0 */
#define JMPm 40 /* jump to label */
#define LABm 41 /* define label m */
#define LE10f 42 /* jump if (pr <= 0) is false */
#define LE12 43 /* set pr TRUE if (sr <= pr) */
#define LE12u 44 /* set pr TRUE if (sr <= pr) unsigned */
#define LNEG1 45 /* logical negate pr */
#define LT10f 46 /* jump if (pr < 0) is false */
#define LT12 47 /* set pr TRUE if (sr < pr) */
#define LT12u 48 /* set pr TRUE if (sr < pr) unsigned */
#define MOD12 49 /* modulo pr by sr */
#define MOD12u 50 /* modulo pr by sr unsigned */
#define MOVE21 51 /* move pr to sr */
#define MUL12 52 /* multiply pr by sr */
#define MUL12u 53 /* multiply pr by sr unsigned */
#define NE10f 54 /* jump if (pr != 0) is false */
#define NE12 55 /* set pr TRUE if (sr != pr) */
#define NEARm 56 /* define near pointer thru label */
#define OR12 57 /* OR sr onto pr */
#define POINT1s 58 /* point pr to stack item */
#define POP2 59 /* pop stack into sr */
#define PUSH1 60 /* push pr onto stack */
#define PUTbm1 61 /* put pr byte in mem thru label */
#define PUTbp1 62 /* put pr byte in mem thru sr ptr */
#define PUTdm1 114 /* put pr dword in mem thru label */
#define PUTdp1 115 /* put pr dword in mem thru sr ptr */
#define PUTwm1 63 /* put pr word in mem thru label */
#define PUTwp1 64 /* put pr word in mem thru sr ptr */
#define rDEC1 65 /* dec pr (may repeat) */
#define REFm 66 /* finish instruction with label */
#define RETURN 67 /* restore stack and return */
#define rINC1 68 /* inc pr (may repeat) */
#define SUB12 69 /* sub sr from pr */
#define SWAP12 70 /* swap pr and sr */
#define SWAP1s 71 /* swap pr and top of stack */
#define SWITCH 72 /* find switch case */
#define XOR12 73 /* XOR pr with sr */
/* optimizer-generated */
#define ADD1n 74 /* add n to pr */
#define ADD21 75 /* add pr to sr */
#define ADD2n 76 /* add immediate to sr */
#define ADDbpn 77 /* add n to mem byte thru sr ptr */
#define ADDwpn 78 /* add n to mem word thru sr ptr */
#define ADDm_ 79 /* add n to mem byte/word thru label (part 1) */
#define COMMAn 80 /* finish instruction with ,n */
#define DECbp 81 /* dec mem byte thru sr ptr */
#define DECwp 82 /* dec mem word thru sr ptr */
#define POINT2m 83 /* point sr to mem thru label */
#define POINT2m_ 84 /* point sr to mem thru label (part 1) */
#define GETb1s 85 /* get byte into pr from stack */
#define GETb1su 86 /* get unsigned byte into pr from stack */
#define GETw1m_ 87 /* get word into pr from mem thru label (part 1) */
#define GETw1s 88 /* get word into pr from stack */
#define GETw2m 89 /* get word into sr from mem (label) */
#define GETw2p 90 /* get word into sr thru sr ptr */
#define GETw2s 91 /* get word into sr from stack */
#define INCbp 92 /* inc byte in mem thru sr ptr */
#define INCwp 93 /* inc word in mem thru sr ptr */
#define PLUSn 94 /* finish instruction with +n */
#define POINT2s 95 /* point sr to stack */
#define PUSH2 96 /* push sr */
#define PUSHm 97 /* push word from mem thru label */
#define PUSHp 98 /* push word from mem thru sr ptr */
#define PUSHs 99 /* push word from stack */
#define PUT_m_ 100 /* put byte/word into mem thru label (part 1) */
#define rDEC2 101 /* dec sr (may repeat) */
#define rINC2 102 /* inc sr (may repeat) */
#define SUB_m_ 103 /* sub from mem byte/word thru label (part 1) */
#define SUB1n 104 /* sub n from pr */
#define SUBbpn 105 /* sub n from mem byte thru sr ptr */
#define SUBwpn 106 /* sub n from mem word thru sr ptr */
#define PCODES 116 /* size of code[] (it's a [+ 1]) */

911
programs/develop/scc/cc1.c Normal file
View File

@ -0,0 +1,911 @@
/*
** Small-C Compiler -- Part 1 -- Top End.
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
** Copyright 1998 H T Walheim
** All rights reserved.
*/
#include <stdio.h>
#include "notice.h"
#include "cc.h"
/*
** miscellaneous storage
*/
int
nogo, /* disable goto statements? */
noloc, /* disable block locals? */
opindex, /* index to matched operator */
opsize, /* size of operator in characters */
swactive, /* inside a switch? */
swdefault,/* default label #, else 0 */
*swnext, /* address of next entry */
*swend, /* address of last entry */
*stage, /* staging buffer address */
*wq, /* while queue */
argcs, /* static argc */
*argvs, /* static argv */
*wqptr, /* ptr to next entry */
litptr, /* ptr to next entry */
macptr, /* macro buffer index */
pptr, /* ptr to parsing buffer */
ch, /* current character of input line */
nch, /* next character of input line */
declared, /* # of local bytes to declare, -1 when declared */
iflevel, /* #if... nest level */
skiplevel,/* level at which #if... skipping started */
nxtlab, /* next avail label # */
litlab, /* label # assigned to literal pool */
csp, /* compiler relative stk ptr */
argstk, /* function arg sp */
argtop, /* highest formal argument offset */
ncmp, /* # open compound statements */
errflag, /* true after 1st error in statement */
eof, /* true on final input eof */
output, /* fd for output file */
files, /* true if file list specified on cmd line */
filearg = 0, /* cur file arg index */
input = EOF, /* fd for input file */
input2 = EOF, /* fd for "#include" file */
usexpr = YES, /* true if value of expression is used */
ccode = YES, /* true while parsing C code */
*snext, /* next addr in stage */
*stail, /* last addr of data in stage */
*slast, /* last addr in stage */
listfp, /* file pointer to list device */
lastst, /* last parsed statement type */
oldseg; /* current segment (0, DATASEG, CODESEG) */
char
optimize, /* optimize output of staging buffer? */
alarm, /* audible alarm on errors? */
monitor, /* monitor function headers? */
pause, /* pause for operator on errors? */
*symtab, /* symbol table */
*litq, /* literal pool */
*macn, /* macro name buffer */
*macq, /* macro string buffer */
*pline, /* parsing buffer */
*mline, /* macro buffer */
*line, /* ptr to pline or mline */
*lptr, /* ptr to current character in "line" */
*glbptr, /* global symbol table */
*locptr, /* next local symbol table entry */
quote[2] = {'"'}, /* literal string for '"' */
*cptr, /* work ptrs to any char buffer */
*cptr2,
*cptr3,
msname[NAMESIZE], /* macro symbol name */
ssname[NAMESIZE]; /* static symbol name */
int op[16] = { /* p-codes of signed binary operators */
OR12, /* level5 */
XOR12, /* level6 */
AND12, /* level7 */
EQ12, NE12, /* level8 */
LE12, GE12, LT12, GT12, /* level9 */
ASR12, ASL12, /* level10 */
ADD12, SUB12, /* level11 */
MUL12, DIV12, MOD12 /* level12 */
};
int op2[16] = { /* p-codes of unsigned binary operators */
OR12, /* level5 */
XOR12, /* level6 */
AND12, /* level7 */
EQ12, NE12, /* level8 */
LE12u, GE12u, LT12u, GT12u, /* level9 */
ASR12, ASL12, /* level10 */
ADD12, SUB12, /* level11 */
MUL12u, DIV12u, MOD12u /* level12 */
};
/*
** execution begins here
*/
main(argc, argv) int argc, *argv; {
fputs(VERSION, stdout);
fputs(CRIGHT1, stdout);
fputs(CRIGHT2, stdout);
argcs = argc;
argvs = argv;
swnext = calloc(SWTABSZ, 1);
swend = swnext+(SWTABSZ-SWSIZ);
stage = calloc(STAGESIZE, 2*INTSIZE);
wqptr =
wq = calloc(WQTABSZ, INTSIZE);
litq = calloc(LITABSZ, 1);
macn = calloc(MACNSIZE, 1);
macq = calloc(MACQSIZE, 1);
pline = calloc(LINESIZE, 1);
mline = calloc(LINESIZE, 1);
slast = stage+(STAGESIZE*2*INTSIZE);
symtab = calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
locptr = STARTLOC;
glbptr = STARTGLB;
ask(); /* get user options */
openfile(); /* and initial input file */
preprocess(); /* fetch first line */
header(); /* intro code */
setcodes(); /* initialize code pointer array */
parse(); /* process ALL input */
trailer(); /* follow-up code */
fclose(output); /* explicitly close output */
}
/******************** high level parsing *******************/
/*
** process all input text
**
** At this level, only static declarations,
** defines, includes and function
** definitions are legal...
*/
parse() {
while (eof == 0) {
if (amatch("extern", 6)) dodeclare(EXTERNAL);
else if(dodeclare(STATIC)) ;
else if( match("#asm")) doasm();
else if( match("#include")) doinclude();
else if( match("#define")) dodefine();
else dofunction();
blanks(); /* force eof if pending */
}
}
/*
** test for global declarations
*/
dodeclare(class) int class; {
if (amatch("char", 4)) declglb(CHR, class);
else if(amatch("unsigned", 8)) {
if (amatch("char", 4)) declglb(UCHR, class);
else {amatch("int", 3); declglb(UINT, class);}
}
else if(amatch("int", 3)
|| class == EXTERNAL) declglb(INT, class);
else return 0;
ns();
return 1;
}
/*
** declare a static variable
*/
declglb(type, class)
int type, class;
{
int id, dim;
while(1)
{
if(endst())
return; /* do line */
if(match("*"))
{
id = POINTER; dim = 0;
}
else
{
id = VARIABLE; dim = 1;
}
if(symname(ssname) == 0)
illname();
if(findglb(ssname))
multidef(ssname);
if(id == VARIABLE)
{
if (match("("))
{
id = FUNCTION; need(")");
}
else if(match("["))
{
id = ARRAY; dim = needsub();
}
}
if (class == EXTERNAL)
external(ssname, type >> 2, id);
else if (id != FUNCTION)
initials(type >> 2, id, dim);
if(id == POINTER)
addsym(ssname, id, type, PTRSIZE, 0, &glbptr, class);
else
addsym(ssname, id, type, dim * (type >> 2), 0, &glbptr, class);
if(match(",") == 0)
return;
}
}
/*
** initialize global objects
*/
initials(size, ident, dim) int size, ident, dim; {
int savedim;
litptr = 0;
if(dim == 0) dim = -1; /* *... or ...[] */
savedim = dim;
/* public(ident); */
if(match("=")) {
if(match("{")) {
while(dim) {
init(size, ident, &dim);
if(match(",") == 0) break;
}
need("}");
}
else init(size, ident, &dim);
}
if(savedim == -1 && dim == -1) {
if(ident == ARRAY) error("need array size");
stowlit(0, size = PTRSIZE);
}
/* FASM */
public(ident);
if(litptr>0) dumplits(size);
else if(dim>0)
{/*In FASM: "<variable>: TIMES <number> D<type> 0" */
fputc(':',output);
}
dumpzero(size, dim); /* only if dim > 0 */
/* FASM */
}
/*
** evaluate one initializer
*/
init(size, ident, dim) int size, ident, *dim; {
int value;
if(string(&value)) {
if(ident == VARIABLE || size != 1)
error("must assign to char pointer or char array");
*dim -= (litptr - value);
if(ident == POINTER) point();
}
else if(constexpr(&value)) {
if(ident == POINTER) error("cannot assign to pointer");
stowlit(value, size);
*dim -= 1;
}
}
/*
** get required array size
*/
needsub() {
int val;
if(match("]")) return 0; /* null size */
if(constexpr(&val) == 0) val = 1;
if(val < 0) {
error("negative size illegal");
val = -val;
}
need("]"); /* force single dimension */
return val; /* and return size */
}
/*
** open an include file
*/
doinclude() {
int i; char str[30];
blanks(); /* skip over to name */
if(*lptr == '"' || *lptr == '<') ++lptr;
i = 0;
while(lptr[i]
&& lptr[i] != '"'
&& lptr[i] != '>'
&& lptr[i] != '\n') {
str[i] = lptr[i];
++i;
}
str[i] = NULL;
if((input2 = fopen(str,"r")) == NULL) {
input2 = EOF;
error("open failure on include file");
}
kill(); /* make next read come from new file (if open) */
}
/*
** define a macro symbol
*/
dodefine() {
int k;
if(symname(msname) == 0) {
illname();
kill();
return;
}
/*
puts (msname);
puts (" is #defined\n");
*/
k = 0;
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0) {
if(cptr2 = cptr)
while(*cptr2++ = msname[k++]) ;
else {
error("macro name table full");
return;
}
}
putint(macptr, cptr+NAMESIZE, 2 /*INTSIZE*/);
while(white()) gch();
while(putmac(gch()));
if(macptr >= MACMAX) {
error("macro string queue full");
exit(ERRCODE);
}
}
putmac(c) char c; {
macq[macptr] = c;
if(macptr < MACMAX) ++macptr;
return c;
}
/*
** begin a function
**
** called from "parse" and tries to make a function
** out of the following text
*/
dofunction() {
char *ptr;
nogo = /* enable goto statements */
noloc = /* enable block-local declarations */
lastst = /* no statement yet */
litptr = 0; /* clear lit pool */
litlab = getlabel(); /* label next lit pool */
locptr = STARTLOC; /* clear local variables */
if(match("void")) blanks(); /* skip "void" & locate header */
if(monitor) lout(line, stderr);
if(symname(ssname) == 0) {
error("illegal function or declaration");
errflag = 0;
kill(); /* invalidate line */
return;
}
if(ptr = findglb(ssname)) { /* already in symbol table? */
if(ptr[CLASS] == AUTOEXT)
ptr[CLASS] = STATIC;
else multidef(ssname);
}
else addsym(ssname, FUNCTION, INT, 0, 0, &glbptr, STATIC);
public(FUNCTION);
argstk = 0; /* init arg count */
if(match("(") == 0) error("no open paren");
while(match(")") == 0) { /* then count args */
if(symname(ssname)) {
if(findloc(ssname)) multidef(ssname);
else {
addsym(ssname, 0, 0, 0, argstk, &locptr, AUTOMATIC);
argstk += INTSIZE;
}
}
else {
error("illegal argument name");
skip();
}
blanks();
if(streq(lptr,")") == 0 && match(",") == 0)
error("no comma");
if(endst()) break;
}
csp = 0; /* preset stack ptr */
argtop = argstk+INTSIZE; /* account for the pushed BP */
while(argstk) {
if (amatch("char", 4)) {doargs(CHR); ns();}
else if(amatch("int", 3)) {doargs(INT); ns();}
else if(amatch("unsigned", 8)) {
if (amatch("char", 4)) {doargs(UCHR); ns();}
else {amatch("int", 3); doargs(UINT); ns();}
}
else {error("wrong number of arguments"); break;}
}
gen(ENTER, 0);
statement();
if(lastst != STRETURN && lastst != STGOTO)
gen(RETURN, 0);
if(litptr) {
toseg(DATASEG);
gen(REFm, litlab);
dumplits(1); /* dump literals */
}
}
/*
** declare argument types
*/
doargs(type) int type; {
int id, sz;
char c, *ptr;
while(1) {
if(argstk == 0) return; /* no arguments */
if(decl(type, POINTER, &id, &sz)) {
if(ptr = findloc(ssname)) {
ptr[IDENT] = id;
ptr[TYPE] = type;
putint(sz, ptr+SIZE, INTSIZE);
putint(argtop-getint(ptr+OFFSET, INTSIZE), ptr+OFFSET, INTSIZE);
}
else error("not an argument");
}
argstk = argstk - INTSIZE; /* cnt down */
if(endst()) return;
if(match(",") == 0) error("no comma");
}
}
/*
** parse next local or argument declaration
*/
decl(type, aid, id, sz)
int type, aid, *id, *sz;
{
int n, p;
int mod;
if(match("(")) p = 1;
else p = 0;
if(match("*")) {*id = POINTER; *sz = PTRSIZE;}
else {*id = VARIABLE; *sz = type >> 2;}
if((n = symname(ssname)) == 0) illname();
if(p && match(")")) ;
if(match("("))
{
if(!p || *id != POINTER)
error("try (*...)()");
need(")");
}
else if(*id == VARIABLE && match("["))
{
*id = aid;
if((*sz *= needsub()) == 0)
{
if(aid == ARRAY) error("need array size");
*sz = PTRSIZE; /* size of pointer argument */
}
}
mod = *sz % ALIGN;
if (mod)
{
*sz = *sz + (ALIGN-mod);
}
return n;
}
/******************** start 2nd level parsing *******************/
/*
** statement parser
*/
statement() {
if(ch == 0 && eof) return;
else if(amatch("char", 4)) {declloc(CHR); ns();}
else if(amatch("int", 3)) {declloc(INT); ns();}
else if(amatch("unsigned", 8)) {
if (amatch("char", 4)) {declloc(UCHR); ns();}
else {amatch("int", 3); declloc(UINT); ns();}
}
else {
if(declared >= 0) {
if(ncmp > 1) nogo = declared; /* disable goto */
gen(ADDSP, csp - declared);
declared = -1;
}
if(match("{")) compound();
else if(amatch("if", 2)) {doif(); lastst = STIF;}
else if(amatch("while", 5)) {dowhile(); lastst = STWHILE;}
else if(amatch("do", 2)) {dodo(); lastst = STDO;}
else if(amatch("for", 3)) {dofor(); lastst = STFOR;}
else if(amatch("switch", 6)) {doswitch(); lastst = STSWITCH;}
else if(amatch("case", 4)) {docase(); lastst = STCASE;}
else if(amatch("default", 7)) {dodefault(); lastst = STDEF;}
else if(amatch("goto", 4)) {dogoto(); lastst = STGOTO;}
else if(dolabel()) lastst = STLABEL;
else if(amatch("return", 6)) {doreturn(); ns(); lastst = STRETURN;}
else if(amatch("break", 5)) {dobreak(); ns(); lastst = STBREAK;}
else if(amatch("continue", 8)) {docont(); ns(); lastst = STCONT;}
else if(match(";")) errflag = 0;
else if(match("#asm")) {doasm(); lastst = STASM;}
else {doexpr(NO); ns(); lastst = STEXPR;}
}
return lastst;
}
/*
** declare local variables
*/
declloc(type) int type; {
int id, sz;
if(swactive) error("not allowed in switch");
if(noloc) error("not allowed with goto");
if(declared < 0) error("must declare first in block");
while(1) {
if(endst()) return;
decl(type, ARRAY, &id, &sz);
declared += sz;
addsym(ssname, id, type, sz, csp - declared, &locptr, AUTOMATIC);
if(match(",") == 0) return;
}
}
compound() {
int savcsp;
char *savloc;
savcsp = csp;
savloc = locptr;
declared = 0; /* may now declare local variables */
++ncmp; /* new level open */
while (match("}") == 0)
if(eof) {
error("no final }");
break;
}
else statement(); /* do one */
if(--ncmp /* close current level */
&& lastst != STRETURN
&& lastst != STGOTO)
gen(ADDSP, savcsp); /* delete local variable space */
cptr = savloc; /* retain labels */
while(cptr < locptr) {
cptr2 = nextsym(cptr);
if(cptr[IDENT] == LABEL) {
while(cptr < cptr2) *savloc++ = *cptr++;
}
else cptr = cptr2;
}
locptr = savloc; /* delete local symbols */
declared = -1; /* may not declare variables */
}
doif() {
int flab1, flab2;
test(flab1 = getlabel(), YES); /* get expr, and branch false */
statement(); /* if true, do a statement */
if(amatch("else", 4) == 0) { /* if...else ? */
/* simple "if"...print false label */
gen(LABm, flab1);
return; /* and exit */
}
flab2 = getlabel();
if(lastst != STRETURN && lastst != STGOTO)
gen(JMPm, flab2);
gen(LABm, flab1); /* print false label */
statement(); /* and do "else" clause */
gen(LABm, flab2); /* print true label */
}
dowhile() {
int wq[4]; /* allocate local queue */
addwhile(wq); /* add entry to queue for "break" */
gen(LABm, wq[WQLOOP]); /* loop label */
test(wq[WQEXIT], YES); /* see if true */
statement(); /* if so, do a statement */
gen(JMPm, wq[WQLOOP]); /* loop to label */
gen(LABm, wq[WQEXIT]); /* exit label */
delwhile(); /* delete queue entry */
}
dodo() {
int wq[4];
addwhile(wq);
gen(LABm, wq[WQLOOP]);
statement();
need("while");
test(wq[WQEXIT], YES);
gen(JMPm, wq[WQLOOP]);
gen(LABm, wq[WQEXIT]);
delwhile();
ns();
}
dofor() {
int wq[4], lab1, lab2;
addwhile(wq);
lab1 = getlabel();
lab2 = getlabel();
need("(");
if(match(";") == 0) {
doexpr(NO); /* expr 1 */
ns();
}
gen(LABm, lab1);
if(match(";") == 0) {
test(wq[WQEXIT], NO); /* expr 2 */
ns();
}
gen(JMPm, lab2);
gen(LABm, wq[WQLOOP]);
if(match(")") == 0) {
doexpr(NO); /* expr 3 */
need(")");
}
gen(JMPm, lab1);
gen(LABm, lab2);
statement();
gen(JMPm, wq[WQLOOP]);
gen(LABm, wq[WQEXIT]);
delwhile();
}
doswitch() {
int wq[4], endlab, swact, swdef, *swnex, *swptr;
swact = swactive;
swdef = swdefault;
swnex = swptr = swnext;
addwhile(wq);
*(wqptr + WQLOOP - WQSIZ) = 0;
need("(");
doexpr(YES); /* evaluate switch expression */
need(")");
swdefault = 0;
swactive = 1;
gen(JMPm, endlab = getlabel());
statement(); /* cases, etc. */
gen(JMPm, wq[WQEXIT]);
gen(LABm, endlab);
gen(SWITCH, 0); /* match cases */
while(swptr < swnext) {
gen(NEARm, *swptr++);
#ifdef INT32
gen(DWORDn, *swptr++); /* case value */
#else
gen(WORDn, *swptr++); /* case value */
#endif
}
#ifdef INT32
gen(DWORDn, 0);
#else
gen(WORDn, 0);
#endif
if(swdefault) gen(JMPm, swdefault);
gen(LABm, wq[WQEXIT]);
delwhile();
swnext = swnex;
swdefault = swdef;
swactive = swact;
}
docase() {
if(swactive == 0) error("not in switch");
if(swnext > swend) {
error("too many cases");
return;
}
gen(LABm, *swnext++ = getlabel());
constexpr(swnext++);
need(":");
}
dodefault() {
if(swactive) {
if(swdefault) error("multiple defaults");
}
else error("not in switch");
need(":");
gen(LABm, swdefault = getlabel());
}
dogoto() {
if(nogo > 0) error("not allowed with block-locals");
else noloc = 1;
if(symname(ssname)) gen(JMPm, addlabel(NO));
else error("bad label");
ns();
}
dolabel() {
char *savelptr;
blanks();
savelptr = lptr;
if(symname(ssname)) {
if(gch() == ':') {
gen(LABm, addlabel(YES));
return 1;
}
else bump(savelptr-lptr);
}
return 0;
}
addlabel(def) int def; {
if(cptr = findloc(ssname)) {
if(cptr[IDENT] != LABEL) error("not a label");
else if(def) {
if(cptr[TYPE]) error("duplicate label");
else cptr[TYPE] = YES;
}
}
else cptr = addsym(ssname, LABEL, def, 0, getlabel(), &locptr, LABEL);
return (getint(cptr+OFFSET, INTSIZE));
}
doreturn() {
int savcsp;
if(endst() == 0) doexpr(YES);
savcsp = csp;
gen(RETURN, 0);
csp = savcsp;
}
dobreak() {
int *ptr;
if((ptr = readwhile(wqptr)) == 0) return;
gen(ADDSP, ptr[WQSP]);
gen(JMPm, ptr[WQEXIT]);
}
docont() {
int *ptr;
ptr = wqptr;
while (1) {
if((ptr = readwhile(ptr)) == 0) return;
if(ptr[WQLOOP]) break;
}
gen(ADDSP, ptr[WQSP]);
gen(JMPm, ptr[WQLOOP]);
}
doasm() {
ccode = 0; /* mark mode as "asm" */
while (1) {
inline();
if(match("#endasm")) break;
if(eof)break;
fputs(line, output);
}
kill();
ccode = 1;
}
doexpr(use) int use; {
int constant, val;
int *before, *start;
usexpr = use; /* tell isfree() whether expr value is used */
while(1) {
setstage(&before, &start);
expression(&constant, &val);
clearstage(before, start);
if(ch != ',') break;
bump(1);
}
usexpr = YES; /* return to normal value */
}
/******************** miscellaneous functions *******************/
/*
** get run options
*/
ask()
{
int i;
int j;
i = listfp = nxtlab = 0;
output = stdout;
#ifdef LATER
optimize = YES; // Not working for 32 bit int's yer
#else
optimize = NO;
#endif
alarm = monitor = pause = NO;
line = mline;
while(getarg(++i, line, LINESIZE, argcs, argvs) != EOF)
{
if(line[0] != '-' && line[0] != '/')
continue;
if(toupper(line[1]) == 'L' // List
&& isdigit(line[2])
&& line[3] <= ' ')
{
listfp = line[2]-'0';
continue;
}
if(toupper(line[1]) == 'N' // No optimize
&& toupper(line[2]) == 'O'
&& line[3] <= ' ')
{
optimize = NO;
continue;
}
if(toupper(line[1]) == 'D')
{
j = 0;
ch = line[j+2];
lptr = line + j+2;
/*
while (line[j+2] != ' ')
{
if (j < (NAMEMAX-1))
{
msname[j] = line[j+1];
++j;
}
else
{
break;
}
}
msname[j] = '\0';
*/
dodefine ();
continue;
}
if(line[2] <= ' ')
{
if(toupper(line[1]) == 'A') {alarm = YES; continue;}
if(toupper(line[1]) == 'M') {monitor = YES; continue;}
if(toupper(line[1]) == 'P') {pause = YES; continue;}
}
fputs("usage: cc [file]... [-m] [-a] [-p] [-l#] [-no] [-d<id>]\n", stderr);
fputs(" -m monitor\n", stderr);
fputs(" -a alarm\n", stderr);
fputs(" -p pause\n", stderr);
fputs(" -l# list\n", stderr);
fputs(" -no no optimize\n", stderr);
fputs(" -d<id> pre-#define id\n", stderr);
exit(ERRCODE);
}
}
/*
** input and output file opens
*/
openfile() { /* entire function revised */
char outfn[15];
int i, j, ext;
input = EOF;
while(getarg(++filearg, pline, LINESIZE, argcs, argvs) != EOF) {
if(pline[0] == '-' || pline[0] == '/') continue;
ext = NO;
i = -1;
j = 0;
while(pline[++i]) {
if(pline[i] == '.') {
ext = YES;
break;
}
if(j < 10) outfn[j++] = pline[i];
}
if(!ext) strcpy(pline + i, ".C");
input = mustopen(pline, "r");
#ifdef _MSC_VER
if(!files) {
strcpy(outfn + j, ".ASM");
output = mustopen(outfn, "w");
}
#else
if(!files /* && iscons(stdout)*/) {
strcpy(outfn + j, ".ASM");
output = mustopen(outfn, "w");
}
#endif
files = YES;
kill();
return;
}
if(files++) eof = YES;
else input = stdin;
kill();
}
/*
** open a file with error checking
*/
mustopen(fn, mode) char *fn, *mode; {
int fd;
if(fd = fopen(fn, mode)) return fd;
fputs("open error on ", stderr);
lout(fn, stderr);
exit(ERRCODE);
}

557
programs/develop/scc/cc2.c Normal file
View File

@ -0,0 +1,557 @@
/*
** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
** Copyright 1998 H T Walheim
** All rights reserved.
*/
#include <stdio.h>
#include "cc.h"
extern char
*symtab, *macn, *macq, *pline, *mline, optimize,
alarm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3,
*locptr, msname[NAMESIZE], pause, quote[2];
extern int
*wq, ccode, ch, csp, eof, errflag, iflevel,
input, input2, listfp, macptr, nch,
nxtlab, op[16], opindex, opsize, output, pptr,
skiplevel, *wqptr;
/********************** input functions **********************/
preprocess() {
int k;
char c;
if(ccode) {
line = mline;
ifline();
if(eof) return;
}
else {
inline();
return;
}
pptr = -1;
while(ch != NEWLINE && ch) {
if(white()) {
keepch(' ');
while(white()) gch();
}
else if(ch == '"') {
keepch(ch);
gch();
while(ch != '"' || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
if(ch == NULL) {
error("no quote");
break;
}
keepch(gch());
}
gch();
keepch('"');
}
else if(ch == 39) {
keepch(39);
gch();
while(ch != 39 || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
if(ch == NULL) {
error("no apostrophe");
break;
}
keepch(gch());
}
gch();
keepch(39);
}
else if(ch == '/' && nch == '*')
{
bump(2);
while((ch == '*' && nch == '/') == 0)
{
if(ch)
bump(1);
else
{
ifline();
if(eof)
break;
}
}
bump(2);
}
else if(ch == '/' && nch == '/')
{
bump(2);
while(ch != NEWLINE)
{
if(ch)
bump(1);
else
{
if(eof)
break;
}
}
bump(1);
}
else if(an(ch)) {
k = 0;
while(an(ch) && k < NAMEMAX) {
msname[k++] = ch;
gch();
}
msname[k] = NULL;
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
k = getint(cptr+NAMESIZE, 2/*INTSIZE*/);
while(c = macq[k++]) keepch(c);
while(an(ch)) gch();
}
else {
k = 0;
while(c = msname[k++]) keepch(c);
}
}
else keepch(gch());
}
if(pptr >= LINEMAX) error("line too long");
keepch(NULL);
line = pline;
bump(0);
}
keepch(c) char c; {
if(pptr < LINEMAX) pline[++pptr] = c;
}
ifline() {
while(1) {
inline();
if(eof) return;
if(match("#ifdef")) {
++iflevel;
if(skiplevel) continue;
symname(msname);
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0)
skiplevel = iflevel;
continue;
}
if(match("#ifndef")) {
++iflevel;
if(skiplevel) continue;
symname(msname);
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
skiplevel = iflevel;
continue;
}
if(match("#else")) {
if(iflevel) {
if(skiplevel == iflevel) skiplevel = 0;
else if(skiplevel == 0) skiplevel = iflevel;
}
else noiferr();
continue;
}
if(match("#endif")) {
if(iflevel) {
if(skiplevel == iflevel) skiplevel = 0;
--iflevel;
}
else noiferr();
continue;
}
if(skiplevel) continue;
if(ch == 0) continue;
break;
}
}
inline() { /* numerous revisions */
int k, unit;
if(input == EOF) openfile();
if(eof) return;
if((unit = input2) == EOF) unit = input;
if(fgets(line, LINEMAX, unit) == NULL) {
fclose(unit);
if(input2 != EOF)
input2 = EOF;
else input = EOF;
*line = NULL;
}
else if(listfp)
{
if(listfp == output) fputc(';', output);
fputs(line, listfp);
}
#ifdef _MSC_VER
else
{
fputc(';', output);
fputs(line, output);
}
#endif
bump(0);
}
inbyte() {
while(ch == 0) {
if(eof) return 0;
preprocess();
}
return gch();
}
/********************* scanning functions ********************/
/*
** test if next input string is legal symbol name
*/
symname(sname) char *sname; {
int k;char c;
blanks();
if(alpha(ch) == 0) return (*sname = 0);
k = 0;
while(an(ch)) {
sname[k] = gch();
if(k < NAMEMAX) ++k;
}
sname[k] = 0;
return 1;
}
need(str) char *str; {
if(match(str) == 0) error("missing token");
}
ns() {
if(match(";") == 0) error("no semicolon");
else errflag = 0;
}
match(lit) char *lit; {
int k;
blanks();
if(k = streq(lptr, lit)) {
bump(k);
return 1;
}
return 0;
}
streq(str1, str2) char str1[], str2[]; {
int k;
k = 0;
while (str2[k]) {
if(str1[k] != str2[k]) return 0;
++k;
}
return k;
}
amatch(lit, len) char *lit; int len; {
int k;
blanks();
if(k = astreq(lptr, lit, len)) {
bump(k);
return 1;
}
return 0;
}
astreq(str1, str2, len) char str1[], str2[]; int len; {
int k;
k = 0;
while (k < len) {
if(str1[k] != str2[k]) break;
/*
** must detect end of symbol table names terminated by
** symbol length in binary
*/
if(str2[k] < ' ') break;
if(str1[k] < ' ') break;
++k;
}
if(an(str1[k]) || an(str2[k])) return 0;
return k;
}
nextop(list) char *list; {
char op[4];
opindex = 0;
blanks();
while(1) {
opsize = 0;
while(*list > ' ') op[opsize++] = *list++;
op[opsize] = 0;
if(opsize = streq(lptr, op))
if(*(lptr+opsize) != '=' &&
*(lptr+opsize) != *(lptr+opsize-1))
return 1;
if(*list) {
++list;
++opindex;
}
else return 0;
}
}
blanks() {
while(1) {
while(ch) {
if(white()) gch();
else return;
}
if(line == mline) return;
preprocess();
if(eof) break;
}
}
white() {
return (*lptr <= ' ' && *lptr);
}
gch() {
int c;
if(c = ch) bump(1);
return c;
}
bump(n) int n; {
if(n) lptr += n;
else lptr = line;
if(ch = nch = *lptr) nch = *(lptr+1);
}
kill() {
*line = 0;
bump(0);
}
skip() {
if(an(inbyte()))
while(an(ch)) gch();
else while(an(ch) == 0) {
if(ch == 0) break;
gch();
}
blanks();
}
endst() {
blanks();
return (streq(lptr, ";") || ch == 0);
}
/*********** symbol table management functions ***********/
addsym(sname, id, type, size, value, lgpp, class)
char *sname, id, type;
int size, value, *lgpp, class;
{
if(lgpp == &glbptr)
{
if(cptr2 = findglb(sname))
return cptr2;
if(cptr == 0)
{
error("global symbol table overflow");
return 0;
}
}
else
{
if(locptr > (ENDLOC-SYMMAX))
{
error("local symbol table overflow");
exit(ERRCODE);
}
cptr = *lgpp;
}
cptr[IDENT] = id;
cptr[TYPE] = type;
cptr[CLASS] = class;
putint(size, cptr + SIZE, INTSIZE);
putint(value, cptr + OFFSET, INTSIZE);
cptr3 = cptr2 = cptr + NAME;
while(an(*sname))
*cptr2++ = *sname++;
if(lgpp == &locptr)
{
*cptr2 = cptr2 - cptr3; /* set length */
*lgpp = ++cptr2;
}
return cptr;
}
/*
** search for symbol match
** on return cptr points to slot found or empty slot
*/
search(sname, buf, len, end, max, off)
char *sname, *buf, *end; int len, max, off; {
cptr =
cptr2 = buf+((hash(sname)%(max-1))*len);
while(*cptr != NULL) {
if(astreq(sname, cptr+off, NAMEMAX)) return 1;
if((cptr = cptr+len) >= end) cptr = buf;
if(cptr == cptr2) return (cptr = 0);
}
return 0;
}
hash(sname) char *sname; {
int i, c;
i = 0;
while(c = *sname++) i = (i << 1) + c;
return i;
}
findglb(sname) char *sname; {
if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME))
return cptr;
return 0;
}
findloc(sname) char *sname; {
cptr = locptr - 1; /* search backward for block locals */
while(cptr > STARTLOC) {
cptr = cptr - *cptr;
if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
cptr = cptr - NAME - 1;
}
return 0;
}
nextsym(entry) char *entry; {
entry = entry + NAME;
while(*entry++ >= ' '); /* find length byte */
return entry;
}
/******** while queue management functions *********/
addwhile(ptr) int ptr[]; {
int k;
ptr[WQSP] = csp; /* and stk ptr */
ptr[WQLOOP] = getlabel(); /* and looping label */
ptr[WQEXIT] = getlabel(); /* and exit label */
if(wqptr == WQMAX) {
error("control statement nesting limit");
exit(ERRCODE);
}
k = 0;
while (k < WQSIZ) *wqptr++ = ptr[k++];
}
readwhile(ptr) int *ptr; {
if(ptr <= wq) {
error("out of context");
return 0;
}
else return (ptr - WQSIZ);
}
delwhile() {
if(wqptr > wq) wqptr -= WQSIZ;
}
/****************** utility functions ********************/
/*
** test if c is alphabetic
*/
alpha(c) char c; {
return (isalpha(c) || c == '_');
}
/*
** test if given character is alphanumeric
*/
an(c) char c; {
return (alpha(c) || isdigit(c));
}
/*
** return next avail internal label number
*/
getlabel() {
return(++nxtlab);
}
/*
** get integer of length len from address addr
** (byte sequence set by "putint")
*/
getint(addr, len) char *addr; int len; {
int i;
i = *(addr + --len); /* high order byte sign extended */
while(len--) i = (i << 8) | *(addr + len) & 255;
return i;
}
/*
** put integer i of length len into address addr
** (low byte first)
*/
putint(i, addr, len) char *addr; int i, len; {
while(len--) {
*addr++ = i;
i = i >> 8;
}
}
lout(line, fd) char *line; int fd; {
fputs(line, fd);
fputc(NEWLINE, fd);
}
/******************* error functions *********************/
illname() {
error("illegal symbol");
skip();
}
multidef(sname) char *sname; {
error("already defined");
}
needlval() {
error("must be lvalue");
}
noiferr() {
error("no matching #if...");
errflag = 0;
}
error(msg)
char msg[];
{
if(errflag)
return;
else
errflag = 1;
lout(line, stderr);
errout(msg, stderr);
if(alarm)
fputc(7, stderr);
if(pause)
while(fgetc(stderr) != NEWLINE);
if(listfp > 0)
errout(msg, listfp);
}
errout(msg, fp) char msg[]; int fp; {
int k;
k = line+2;
while(k++ <= lptr) fputc(' ', fp);
lout("/\\", fp);
fputs("**** ", fp); lout(msg, fp);
}

1093
programs/develop/scc/cc3.c Normal file

File diff suppressed because it is too large Load Diff

985
programs/develop/scc/cc4.c Normal file
View File

@ -0,0 +1,985 @@
/*
** Small-C Compiler -- Part 4 -- Back End.
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
** Copyright 1998 H T Walheim
** All rights reserved.
*/
#include <stdio.h>
#include "cc.h"
/* #define DISOPT */ /* display optimizations values */
/*************************** externals ****************************/
extern char
*cptr, *macn, *litq, *symtab, optimize, ssname[NAMESIZE];
extern int
*stage, litlab, litptr, csp, output, oldseg, usexpr,
*snext, *stail, *slast;
/***************** optimizer command definitions ******************/
/* -- p-codes must not overlap these */
#define any 0x00FF /* matches any p-code */
#define _pop 0x00FE /* matches if corresponding POP2 exists */
#define pfree 0x00FD /* matches if pri register free */
#define sfree 0x00FC /* matches if sec register free */
#define comm 0x00FB /* matches if registers are commutative */
/* -- these digits are reserved for n */
#define go 0x0100 /* go n entries */
#define gc 0x0200 /* get code from n entries away */
#define gv 0x0300 /* get value from n entries away */
#define sum 0x0400 /* add value from nth entry away */
#define neg 0x0500 /* negate the value */
#define ife 0x0600 /* if value == n do commands to next 0 */
#define ifl 0x0700 /* if value < n do commands to next 0 */
#define swv 0x0800 /* swap value with value n entries away */
#define topop 0x0900 /* moves |code and current value to POP2 */
#define p1 0x0001 /* plus 1 */
#define p2 0x0002 /* plus 2 */
#define p3 0x0003 /* plus 3 */
#define p4 0x0004 /* plus 4 */
#define m1 0x00FF /* minus 1 */
#define m2 0x00FE /* minus 2 */
#define m3 0x00FD /* minus 3 */
#define m4 0x00FC /* minus 4 */
#define PRI 0030 /* primary register bits */
#define SEC 0003 /* secondary register bits */
#define USES 0011 /* use register contents */
#define ZAPS 0022 /* zap register contents */
#define PUSHES 0100 /* pushes onto the stack */
#define COMMUTES 0200 /* commutative p-code */
/******************** optimizer command lists *********************/
int
seq00[] = {0,ADD12,MOVE21,0, /* ADD21 */
go|p1,ADD21,0},
seq01[] = {0,ADD1n,0, /* rINC1 or rDEC1 ? */
ifl|m2,0,ifl|0,rDEC1,neg,0,ifl|p3,rINC1,0,0},
seq02[] = {0,ADD2n,0, /* rINC2 or rDEC2 ? */
ifl|m2,0,ifl|0,rDEC2,neg,0,ifl|p3,rINC2,0,0},
seq03[] = {0,rDEC1,PUTbp1,rINC1,0, /* SUBbpn or DECbp */
go|p2,ife|p1,DECbp,0,SUBbpn,0},
seq04[] = {0,rDEC1,PUTwp1,rINC1,0, /* SUBwpn or DECwp */
go|p2,ife|p1,DECwp,0,SUBwpn,0},
seq05[] = {0,rDEC1,PUTbm1,rINC1,0, /* SUB_m_ COMMAn */
go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
seq06[] = {0,rDEC1,PUTwm1,rINC1,0, /* SUB_m_ COMMAn */
go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
seq07[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1p,0, /* GETw2m GETb1p */
go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
seq08[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1pu,0, /* GETw2m GETb1pu */
go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
seq09[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETw1p,0, /* GETw2m GETw1p */
go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
seq10[] = {0,GETw1m,GETw2m,SWAP12,0, /* GETw2m GETw1m */
go|p2,GETw1m,gv|m1,go|m1,gv|m1,0},
seq11[] = {0,GETw1m,MOVE21,0, /* GETw2m */
go|p1,GETw2m,gv|m1,0},
seq12[] = {0,GETw1m,PUSH1,pfree,0, /* PUSHm */
go|p1,PUSHm,gv|m1,0},
seq13[] = {0,GETw1n,PUTbm1,pfree,0, /* PUT_m_ COMMAn */
PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
seq14[] = {0,GETw1n,PUTwm1,pfree,0, /* PUT_m_ COMMAn */
PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
seq15[] = {0,GETw1p,PUSH1,pfree,0, /* PUSHp */
go|p1,PUSHp,gv|m1,0},
seq16[] = {0,GETw1s,GETw2n,ADD12,MOVE21,0, /* GETw2s ADD2n */
go|p3,ADD2n,gv|m2,go|m1,GETw2s,gv|m2,0},
seq17[] = {0,GETw1s,GETw2s,SWAP12,0, /* GETw2s GETw1s */
go|p2,GETw1s,gv|m1,go|m1,GETw2s,gv|m1,0},
seq18[] = {0,GETw1s,MOVE21,0, /* GETw2s */
go|p1,GETw2s,gv|m1,0},
seq19[] = {0,GETw2m,GETw1n,SWAP12,SUB12,0, /* GETw1m SUB1n */
go|p3,SUB1n,gv|m2,go|m1,GETw1m,gv|m2,0},
seq20[] = {0,GETw2n,ADD12,0, /* ADD1n */
go|p1,ADD1n,gv|m1,0},
seq21[] = {0,GETw2s,GETw1n,SWAP12,SUB12,0, /* GETw1s SUB1n */
go|p3,SUB1n,gv|m2,go|m1,GETw1s,gv|m2,0},
seq22[] = {0,rINC1,PUTbm1,rDEC1,0, /* ADDm_ COMMAn */
go|p1,ADDm_,go|p1,COMMAn,go|m1,0},
seq23[] = {0,rINC1,PUTwm1,rDEC1,0, /* ADDm_ COMMAn */
go|p1,ADDm_,go|p1,COMMAn,go|m1,0},
seq24[] = {0,rINC1,PUTbp1,rDEC1,0, /* ADDbpn or INCbp */
go|p2,ife|p1,INCbp,0,ADDbpn,0},
seq25[] = {0,rINC1,PUTwp1,rDEC1,0, /* ADDwpn or INCwp */
go|p2,ife|p1,INCwp,0,ADDwpn,0},
seq26[] = {0,MOVE21,GETw1n,SWAP12,SUB12,0, /* SUB1n */
go|p3,SUB1n,gv|m2,0},
seq27[] = {0,MOVE21,GETw1n,comm,0, /* GETw2n comm */
go|p1,GETw2n,0},
seq28[] = {0,POINT1m,GETw2n,ADD12,MOVE21,0, /* POINT2m_ PLUSn */
go|p3,PLUSn,gv|m2,go|m1,POINT2m_,gv|m2,0},
seq29[] = {0,POINT1m,MOVE21,pfree,0, /* POINT2m */
go|p1,POINT2m,gv|m1,0},
seq30[] = {0,POINT1m,PUSH1,pfree,_pop,0, /* ... POINT2m */
topop|POINT2m,go|p2,0},
seq31[] = {0,POINT1s,GETw2n,ADD12,MOVE21,0, /* POINT2s */
sum|p1,go|p3,POINT2s,gv|m3,0},
seq32[] = {0,POINT1s,PUSH1,MOVE21,0, /* POINT2s PUSH2 */
go|p1,POINT2s,gv|m1,go|p1,PUSH2,go|m1,0},
seq33[] = {0,POINT1s,PUSH1,pfree,_pop,0, /* ... POINT2s */
topop|POINT2s,go|p2,0},
seq34[] = {0,POINT1s,MOVE21,0, /* POINT2s */
go|p1,POINT2s,gv|m1,0},
seq35[] = {0,POINT2m,GETb1p,sfree,0, /* GETb1m */
go|p1,GETb1m,gv|m1,0},
seq36[] = {0,POINT2m,GETb1pu,sfree,0, /* GETb1mu */
go|p1,GETb1mu,gv|m1,0},
seq37[] = {0,POINT2m,GETw1p,sfree,0, /* GETw1m */
go|p1,GETw1m,gv|m1,0},
seq38[] = {0,POINT2m_,PLUSn,GETw1p,sfree,0, /* GETw1m_ PLUSn */
go|p2,gc|m1,gv|m1,go|m1,GETw1m_,gv|m1,0},
seq39[] = {0,POINT2s,GETb1p,sfree,0, /* GETb1s */
sum|p1,go|p1,GETb1s,gv|m1,0},
seq40[] = {0,POINT2s,GETb1pu,sfree,0, /* GETb1su */
sum|p1,go|p1,GETb1su,gv|m1,0},
seq41[] = {0,POINT2s,GETw1p,PUSH1,pfree,0, /* PUSHs */
sum|p1,go|p2,PUSHs,gv|m2,0},
seq42[] = {0,POINT2s,GETw1p,sfree,0, /* GETw1s */
sum|p1,go|p1,GETw1s,gv|m1,0},
seq43[] = {0,PUSH1,any,POP2,0, /* MOVE21 any */
go|p2,gc|m1,gv|m1,go|m1,MOVE21,0},
seq44[] = {0,PUSHm,_pop,0, /* ... GETw2m */
topop|GETw2m,go|p1,0},
seq45[] = {0,PUSHp,any,POP2,0, /* GETw2p ... */
go|p2,gc|m1,gv|m1,go|m1,GETw2p,gv|m1,0},
seq46[] = {0,PUSHs,_pop,0, /* ... GETw2s */
topop|GETw2s,go|p1,0},
seq47[] = {0,SUB1n,0, /* rDEC1 or rINC1 ? */
ifl|m2,0,ifl|0,rINC1,neg,0,ifl|p3,rDEC1,0,0};
#define HIGH_SEQ 47
int seq[HIGH_SEQ + 1];
setseq() {
seq[ 0] = seq00; seq[ 1] = seq01; seq[ 2] = seq02; seq[ 3] = seq03;
seq[ 4] = seq04; seq[ 5] = seq05; seq[ 6] = seq06; seq[ 7] = seq07;
seq[ 8] = seq08; seq[ 9] = seq09; seq[10] = seq10; seq[11] = seq11;
seq[12] = seq12; seq[13] = seq13; seq[14] = seq14; seq[15] = seq15;
seq[16] = seq16; seq[17] = seq17; seq[18] = seq18; seq[19] = seq19;
seq[20] = seq20; seq[21] = seq21; seq[22] = seq22; seq[23] = seq23;
seq[24] = seq24; seq[25] = seq25; seq[26] = seq26; seq[27] = seq27;
seq[28] = seq28; seq[29] = seq29; seq[30] = seq30; seq[31] = seq31;
seq[32] = seq32; seq[33] = seq33; seq[34] = seq34; seq[35] = seq35;
seq[36] = seq36; seq[37] = seq37; seq[38] = seq38; seq[39] = seq39;
seq[40] = seq40; seq[41] = seq41; seq[42] = seq42; seq[43] = seq43;
seq[44] = seq44; seq[45] = seq45; seq[46] = seq46; seq[47] = seq47;
}
/***************** assembly-code strings ******************/
int code[PCODES];
/*
** First byte contains flag bits indicating:
** the value in ax is needed (010) or zapped (020)
** the value in bx is needed (001) or zapped (002)
*/
setcodes() {
setseq();
code[ADD12] = "\211ADD EAX,EBX\15\n";
code[ADD1n] = "\010?ADD EAX,<n>\15\n??";
code[ADD21] = "\211ADD EBX,EAX\15\n";
code[ADD2n] = "\010?ADD EBX,<n>\15\n??";
code[ADDbpn] = "\001ADD BYTE [EBX],<n>\15\n";
code[ADDwpn] = "\001ADD WORD [EBX],<n>\15\n";
code[ADDm_] = "\000ADD <m>";
code[ADDSP] = "\000?ADD ESP,<n>\15\n??";
code[AND12] = "\211AND EAX,EBX\15\n";
code[ANEG1] = "\010NEG EAX\15\n";
code[ARGCNTn] = "\000?MOV CL,<n>?XOR CL,CL?\15\n";
code[ASL12] = "\011MOV ECX,EAX\15\nMOV EAX,EBX\15\nSAL EAX,CL\15\n";
code[ASR12] = "\011MOV ECX,EAX\15\nMOV EAX,EBX\15\nSAR EAX,CL\15\n";
code[CALL1] = "\010CALL EAX\15\n";
code[CALLm] = "\020CALL <m>\15\n";
code[BYTE_] = "\000 DB ";
code[BYTEn] = "\000 RESB <n>\15\n";
code[BYTEr0] = "\000 TIMES <n> DB 0\15\n";
code[COM1] = "\010NOT EAX\15\n";
code[COMMAn] = "\000,<n>\15\n";
code[DBL1] = "\010SHL EAX,1\15\n";
code[DBL2] = "\001SHL EBX,1\15\n";
code[DECbp] = "\001DEC BYTE [EBX]\15\n";
code[DECwp] = "\001DEC WORD [EBX]\15\n";
code[DIV12] = "\011CDQ\15\nIDIV EBX\15\n"; /* see gen() */
code[DIV12u] = "\011XOR EDX,EDX\15\nDIV EBX\15\n"; /* see gen() */
code[DWORD_] = "\000 DD ";
code[DWORDn] = "\000 DD <n>\15\n";
code[DWORDr0] = "\000 TIMES <n> DD 0\15\n";
code[ENTER] = "\100PUSH EBP\15\nMOV EBP,ESP\15\n";
code[EQ10f] = "\010<g>OR EAX,EAX\15\nJE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
code[EQ12] = "\211CALL __eq\15\n";
code[GE10f] = "\010<g>OR EAX,EAX\15\nJGE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
code[GE12] = "\011CALL __ge\15\n";
code[GE12u] = "\011CALL __uge\15\n";
code[GETb1m] = "\020MOVSX EAX,BYTE [<m>]\15\n";
code[GETb1mu] = "\020MOVZX EAX,BYTE [<m>]\15\n";
code[GETb1p] = "\021MOVSX EAX,BYTE [EBX?<o>??]\15\n"; /* see gen() */
code[GETb1pu] = "\021MOVZX EAX,BYTE [EBX?<o>??]\15\n"; /* see gen() */
code[GETb1s] = "\020MOVSX EAX,BYTE [EBP<o>]\15\n";
code[GETb1su] = "\020MOVZX EAX,BYTE [EBP<o>]\15\n";
code[GETd1m] = "\020MOV EAX,[<m>]\15\n";
code[GETd1n] = "\020?MOV EAX,<n>?XOR EAX,EAX?\15\n";
code[GETd1p] = "\021MOV EAX, [EBX?<o>??]\15\n"; /* see gen() */
code[GETd2n] = "\002?MOV EBX,<n>?XOR EBX,EBX?\15\n";
code[GETw1m] = "\020MOVSX EAX,WORD [<m>]\15\n";
code[GETw1m_] = "\020MOVSX EAX,WORD [<m>]";
code[GETw1n] = "\020?MOV EAX,<n>?XOR EAX,EAX?\15\n";
code[GETw1p] = "\021MOVSX EAX, WORD [EBX?<o>??]\15\n"; /* see gen() */
code[GETw1s] = "\020MOVSX EAX, WORD [EBP<o>]\15\n";
code[GETw2m] = "\002MOVSX EBX,WORD <m>\15\n";
code[GETw2n] = "\002?MOV EBX,<n>?XOR EBX,EBX?\15\n";
code[GETw2p] = "\021MOVSX EBX,WORD [EBX?<o>??]\15\n";
code[GETw2s] = "\002MOVSX EBX,WORD [EBP<o>]\15\n";
code[GT10f] = "\010<g>OR EAX,EAX\15\nJG _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
code[GT12] = "\010CALL __gt\15\n";
code[GT12u] = "\011CALL __ugt\15\n";
code[INCbp] = "\001INC BYTE [EBX]\15\n";
code[INCwp] = "\001INC WORD [EBX]\15\n";
code[WORD_] = "\000 DW ";
code[WORDn] = "\000 RESW <n>\15\n";
code[WORDr0] = "\000 TIMES <n> DW 0\15\n";
code[JMPm] = "\000JMP _<n>\15\n";
code[LABm] = "\000_<n>:\15\n";
code[LE10f] = "\010<g>OR EAX,EAX\15\nJLE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
code[LE12] = "\011CALL __le\15\n";
code[LE12u] = "\011CALL __ule\15\n";
code[LNEG1] = "\010CALL __lneg\15\n";
code[LT10f] = "\010<g>OR EAX,EAX\15\nJL _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
code[LT12] = "\011CALL __lt\15\n";
code[LT12u] = "\011CALL __ult\15\n";
code[MOD12] = "\011CDQ\15\nIDIV EBX\15\nMOV EAX,EDX\15\n"; /* see gen() */
code[MOD12u] = "\011XOR EDX,EDX\15\nDIV EBX\15\nMOV EAX,EDX\15\n"; /* see gen() */
code[MOVE21] = "\012MOV EBX,EAX\15\n";
code[MUL12] = "\211IMUL EBX\15\n";
code[MUL12u] = "\211MUL EBX\15\n";
code[NE10f] = "\010<g>OR EAX,EAX\15\nJNE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
code[NE12] = "\211CALL __ne\15\n";
code[NEARm] = "\000 DD _<n>\15\n";
code[OR12] = "\211OR EAX,EBX\15\n";
code[PLUSn] = "\000?+<n>??\15\n";
code[POINT1l] = "\020MOV EAX,_<l>+<n>\15\n";
code[POINT1m] = "\020MOV EAX,<m>\15\n";
code[POINT1s] = "\020LEA EAX,[EBP<o>]\15\n";
code[POINT2m] = "\002MOV EBX,<m>\15\n";
code[POINT2m_]= "\002MOV EBX,<m>";
code[POINT2s] = "\002LEA EBX,[EBP<o>]\15\n";
code[POP2] = "\002POP EBX\15\n";
code[PUSH1] = "\110PUSH EAX\15\n";
code[PUSH2] = "\101PUSH EBX\15\n";
code[PUSHm] = "\100PUSH <m>\15\n";
code[PUSHp] = "\100PUSH [EBX?<o>??]\15\n";
code[PUSHs] = "\100PUSH [EBP?<o>??]\15\n";
code[PUT_m_] = "\000MOV <m>";
code[PUTbm1] = "\010MOV BYTE [<m>],AL\15\n";
code[PUTbp1] = "\011MOV [EBX],AL\15\n";
code[PUTdm1] = "\010MOV DWORD [<m>],EAX\15\n";
code[PUTdp1] = "\011MOV [EBX],EAX\15\n";
code[PUTwm1] = "\010MOV WORD [<m>],AX\15\n";
code[PUTwp1] = "\011MOV [EBX],AX\15\n";
code[rDEC1] = "\010#DEC EAX\15\n#";
code[rDEC2] = "\010#DEC EBX\15\n#";
code[REFm] = "\000_<n>";
code[RETURN] = "\000?MOV ESP,EBP\15\n??POP EBP\15\nRET\15\n";
code[rINC1] = "\010#INC EAX\15\n#";
code[rINC2] = "\010#INC EBX\15\n#";
code[SUB_m_] = "\000SUB <m>";
code[SUB12] = "\011SUB EAX,EBX\15\n"; /* see gen() */
code[SUB1n] = "\010?SUB EAX,<n>\15\n??";
code[SUBbpn] = "\001SUB [EBX],<n>\15\n";
code[SUBwpn] = "\001SUB [EBX],<n>\15\n";
code[SWAP12] = "\011XCHG EAX,EBX\15\n";
code[SWAP1s] = "\012POP EBX\15\nXCHG EAX,EBX\15\nPUSH EBX\15\n";
code[SWITCH] = "\012CALL __switch\15\n";
code[XOR12] = "\211XOR EAX,EBX\15\n";
}
/***************** code generation functions *****************/
/*
** print all assembler info before any code is generated
** and ensure that the segments appear in the correct order.
*/
header() {
/* outline(" .386");
outline(" .MODEL FLAT");
*/ toseg(CODESEG);
/* - FASM
outline("EXTERN __eq");
outline("EXTERN __ne");
outline("EXTERN __le");
outline("EXTERN __lt");
outline("EXTERN __ge");
outline("EXTERN __gt");
outline("EXTERN __ule");
outline("EXTERN __ult");
outline("EXTERN __uge");
outline("EXTERN __ugt");
outline("EXTERN __lneg");
outline("EXTERN __switch");
*/
/* outline("dw 0"); *//* force non-zero code pointers, word alignment */
toseg(DATASEG);
/* outline("dw 0"); *//* force non-zero data pointers, word alignment */
}
/*
** print any assembler stuff needed at the end
*/
trailer() {
char *cp;
cptr = STARTGLB;
while(cptr < ENDGLB) {
if(cptr[IDENT] == FUNCTION && cptr[CLASS] == AUTOEXT)
external(cptr + NAME, 0, FUNCTION);
cptr += SYMMAX;
}
/*
if((cp = findglb("main")) && cp[CLASS]==STATIC)
external("_main", 0, FUNCTION);
*/
toseg(NULL);
/* outline("END"); */
#ifdef DISOPT
{
int i, *count;
printf(";opt count\n");
for(i = -1; ++i <= HIGH_SEQ; ) {
count = seq[i];
printf("; %2u %5u\n", i, *count);
}
}
#endif
}
/*
** remember where we are in the queue in case we have to back up.
*/
setstage(before, start) int *before, *start; {
if((*before = snext) == 0)
snext = stage;
*start = snext;
}
/*
** generate code in staging buffer.
*/
gen(pcode, value)
int pcode, value;
{
int newcsp;
switch(pcode)
{
case GETb1pu:
case GETb1p:
case GETw1p:
case GETd1p:
gen(MOVE21, 0);
break;
case SUB12:
case MOD12:
case MOD12u:
case DIV12:
case DIV12u:
gen(SWAP12, 0);
break;
case PUSH1:
#ifdef INT32
csp -= BPD;
#else
csp -= BPW;
#endif
break;
case POP2:
#ifdef INT32
csp += BPD;
#else
csp += BPW;
#endif
break;
case ADDSP:
case RETURN:
newcsp = value;
value -= csp;
csp = newcsp;
}
if(snext == 0)
{
outcode(pcode, value);
return;
}
if(snext >= slast)
{
error("staging buffer overflow");
return;
}
snext[0] = pcode;
snext[1] = value;
snext += 2;
}
/*
** dump the contents of the queue.
** If start = 0, throw away contents.
** If before != 0, don't dump queue yet.
*/
clearstage(before, start)
int *before, *start;
{
if(before)
{
snext = before;
return;
}
if(start)
dumpstage();
snext = 0;
}
/*
** dump the staging buffer
*/
dumpstage()
{
int i;
stail = snext;
snext = stage;
while(snext < stail)
{
if(optimize)
{
restart:
i = -1;
while(++i <= HIGH_SEQ)
if(peep(seq[i]))
{
#ifdef DISOPT
if(isatty(output))
fprintf(stderr, " optimized %2u\n", i);
#endif
goto restart;
}
}
outcode(snext[0], snext[1]);
snext += 2;
}
}
/*
** change to a new segment
** may be called with NULL, CODESEG, or DATASEG
** With NASM the section names are case-sensitive
*/
toseg(newseg)
int newseg;
{
if(oldseg == newseg)
return;
/* if(oldseg == CODESEG)
outline("_TEXT ENDS");
else if(oldseg == DATASEG)
outline("_DATA ENDS"); <-- */
/* - FASM
if(newseg == CODESEG)
{
outline("SECTION .text");
}
else if(newseg == DATASEG)
outline("SECTION .data");
*/
oldseg = newseg;
}
/*
** declare entry point
*/
public(ident) int ident;{
if(ident == FUNCTION)
toseg(CODESEG);
else toseg(DATASEG);
/* - FASM
outstr("GLOBAL ");
outname(ssname);
*/
newline();
outname(ssname);
if(ident == FUNCTION) {
colon();
newline();
}
}
/*
** declare external reference
*/
external(name, size, ident) char *name; int size, ident; {
if(ident == FUNCTION)
toseg(CODESEG);
else toseg(DATASEG);
/* - FASM
outstr("EXTERN ");
outname(name);
/# colon();
outsize(size, ident); <-- #/
newline();
*/
}
/*
** output the size of the object pointed to.
*/
outsize(size, ident) int size, ident;
{
/* why not size on FUNCTION and POINTER ? */
if (ident == FUNCTION)
outstr("NEAR");
else if (ident == POINTER)
outstr("DWORD");
else if(size == 1)
outstr("BYTE");
else if(size == 2)
outstr("WORD");
else
outstr("DWORD");
}
/*
** point to following object(s)
*/
point() {
outline(" DW $+2");
}
/*
** dump the literal pool
*/
dumplits(size) int size;
{
int j, k;
k = 0;
while (k < litptr)
{
if(size == 1)
{
gen(BYTE_, NULL);
}
else if (size == 2)
{
gen(WORD_, NULL);
}
else
{
gen(DWORD_,NULL);
}
j = 10;
while(j--)
{
outdec(getint(litq + k, size));
k += size;
if(j == 0 || k >= litptr)
{
newline();
break;
}
fputc(',', output);
}
}
}
/*
** dump zeroes for default initial values
*/
dumpzero(size, count)
int size, count;
{
if(count > 0)
{
if(size == 1)
gen(BYTEr0, count);
else if (size == 2)
gen(WORDr0, count);
else
gen(DWORDr0, count);
}
}
/******************** optimizer functions ***********************/
/*
** Try to optimize sequence at snext in the staging buffer.
*/
peep(seq) int *seq; {
int *next, *count, *pop, n, skip, tmp, reply;
char c;
next = snext;
count = seq++;
while(*seq) {
switch(*seq) {
case any: if(next < stail) break; return (NO);
case pfree: if(isfree(PRI, next)) break; return (NO);
case sfree: if(isfree(SEC, next)) break; return (NO);
case comm: if(*next & COMMUTES) break; return (NO);
case _pop: if(pop = getpop(next)) break; return (NO);
default: if(next >= stail || *next != *seq) return (NO);
}
next += 2; ++seq;
}
/****** have a match, now optimize it ******/
*count += 1;
reply = skip = NO;
while(*(++seq) || skip) {
if(skip) {
if(*seq == 0) skip = NO;
continue;
}
if(*seq >= PCODES) {
c = *seq & 0xFF; /* get low byte of command */
n = c; /* and sign extend into n */
switch(*seq & 0xFF00) {
case ife: if(snext[1] != n) skip = YES; break;
case ifl: if(snext[1] >= n) skip = YES; break;
case go: snext += (n<<1); break;
case gc: snext[0] = snext[(n<<1)]; goto done;
case gv: snext[1] = snext[(n<<1)+1]; goto done;
case sum: snext[1] += snext[(n<<1)+1]; goto done;
case neg: snext[1] = -snext[1]; goto done;
case topop: pop[0] = n; pop[1] = snext[1]; goto done;
case swv: tmp = snext[1];
snext[1] = snext[(n<<1)+1];
snext[(n<<1)+1] = tmp;
done: reply = YES;
break;
}
}
else snext[0] = *seq; /* set p-code */
}
return (reply);
}
/*
** Is the primary or secondary register free?
** Is it zapped or unused by the p-code at pp
** or a successor? If the primary register is
** unused by it still may not be free if the
** context uses the value of the expression.
*/
isfree(reg, pp) int reg, *pp; {
char *cp;
while(pp < stail) {
cp = code[*pp];
if(*cp & USES & reg) return (NO);
if(*cp & ZAPS & reg) return (YES);
pp += 2;
}
if(usexpr) return (reg & 001); /* PRI => NO, SEC => YES at end */
else return (YES);
}
/*
** Get place where the currently pushed value is popped?
** NOTE: Function arguments are not popped, they are
** wasted with an ADDSP.
*/
getpop(next) int *next; {
char *cp;
int level; level = 0;
while(YES) {
if(next >= stail) /* compiler error */
return 0;
if(*next == POP2)
if(level) --level;
else return next; /* have a matching POP2 */
else if(*next == ADDSP) { /* after func call */
if((level -= (next[1]>>LBPW)) < 0)
return 0;
}
else {
cp = code[*next]; /* code string ptr */
if(*cp & PUSHES) ++level; /* must be a push */
}
next += 2;
}
}
/******************* output functions *********************/
colon() {
fputc(':', output);
}
newline() {
fputc('\15', output);
fputc(NEWLINE, output);
}
/*
** output assembly code.
**
*/
outcode(pcode, value)
int pcode, value;
{
int part, skip, count;
int byte_opt;
char *cp, *back;
int loc_label;
part = back = 0;
skip = NO;
byte_opt = 0;
cp = code[pcode] + 1; /* skip 1st byte of code string */
#ifdef _MSC_VER
switch (pcode)
{
case BYTE_:
case BYTEn:
case BYTEr0:
case WORD_:
case WORDn:
case WORDr0:
case DWORD_:
case DWORDn:
case DWORDr0:
case REFm:
case COMMAn:
case PLUSn:
break;
default:
dump_debug (pcode, value);
outtab ();
}
#endif
if (pcode == ADD1n)
{
if (value < 0)
{
pcode = SUB1n;
value = -value;
}
if (value < 128)
{
byte_opt = 1;
}
}
while(*cp)
{
if(*cp == '<')
{
++cp; /* skip to action code */
if(skip == NO)
switch(*cp)
{
case 'm':
outname(value+NAME);
break; /* mem ref by label */
case 'n':
if (byte_opt)
{
outstr ("BYTE ");
}
outdec(value);
break; /* numeric constant */
case 'o':
offset(value);
break; /* numeric constant */
case 'l':
outdec(litlab);
break; /* current literal label */
case 'g': /* generate local label */
loc_label = getlabel ();
break;
case 'd': /* dump local label */
outdec(loc_label);
break;
}
cp += 2; /* skip past > */
}
else if(*cp == '?') /* ?..if value...?...if not value...? */
{
switch(++part)
{
case 1:
if(value == 0)
skip = YES;
break;
case 2:
skip = !skip;
break;
case 3:
part = 0;
skip = NO;
break;
}
++cp; /* skip past ? */
}
else if(*cp == '#')
{ /* repeat #...# value times */
++cp;
if(back == 0)
{
if((count = value) < 1)
{
while(*cp && *cp++ != '#')
;
continue;
}
back = cp;
continue;
}
if(--count > 0)
cp = back;
else
back = 0;
}
else if(skip == NO)
fputc(*cp++, output);
else
++cp;
}
}
outdec(number) int number; {
int k, zs;
char c, *q, *r;
zs = 0;
k = 1000000000;
#ifdef _MSC_VER
// fprintf(output, "/* %d */", number);
#endif
if(number < 0) {
number = -number;
fputc('-', output);
}
while (k >= 1) {
q = 0;
r = number;
while(r >= k) {++q; r = r - k;}
c = q + '0';
if(c != '0' || k == 1 || zs) {
zs = 1;
fputc(c, output);
}
number = r;
k /= 10;
}
}
offset(number)
int number;
{
int k, zs;
char c, *q, *r;
zs = 0;
k = 1000000000;
if(number < 0) {
number = -number;
fputc('-', output);
}
else
{
fputc('+',output);
}
while (k >= 1) {
q = 0;
r = number;
while(r >= k) {++q; r = r - k;}
c = q + '0';
if(c != '0' || k == 1 || zs) {
zs = 1;
fputc(c, output);
}
number = r;
k /= 10;
}
}
outline(ptr) char ptr[]; {
outstr(ptr);
newline();
}
outname(ptr) char ptr[]; {
outstr("_");
while(*ptr >= ' ') fputc(*ptr++, output);
}
outstr(ptr) char ptr[]; {
while(*ptr == '\t' || *ptr >= ' ') fputc(*ptr++, output);
}
outtab ()
{
fputc ('\t', output);
}