scc 0.5.3
git-svn-id: svn://kolibrios.org@718 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
9a8b3fd945
commit
1967c25fac
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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:
|
|
@ -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 */
|
||||
|
|
@ -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]) */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue