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
4131
programs/develop/scc/CC4.ASM
Normal file
4131
programs/develop/scc/CC4.ASM
Normal file
File diff suppressed because it is too large
Load Diff
5066
programs/develop/scc/Cc1.asm
Normal file
5066
programs/develop/scc/Cc1.asm
Normal file
File diff suppressed because it is too large
Load Diff
3034
programs/develop/scc/Cc2.asm
Normal file
3034
programs/develop/scc/Cc2.asm
Normal file
File diff suppressed because it is too large
Load Diff
6740
programs/develop/scc/Cc3.asm
Normal file
6740
programs/develop/scc/Cc3.asm
Normal file
File diff suppressed because it is too large
Load Diff
128
programs/develop/scc/GETARG.ASM
Normal file
128
programs/develop/scc/GETARG.ASM
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
_getarg:
|
||||
PUSH EBP
|
||||
MOV EBP,ESP
|
||||
ADD ESP,-8
|
||||
LEA EAX,[EBP+24]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
MOV EBX,EAX
|
||||
XOR EAX,EAX
|
||||
CALL __lt
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP+24]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP+12]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
CALL __ge
|
||||
POP EBX
|
||||
OR EAX,EBX
|
||||
OR EAX,EAX
|
||||
JNE _0_3
|
||||
JMP _0_2
|
||||
_0_3:
|
||||
LEA EAX,[EBP+20]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
MOV EBX,EAX
|
||||
XOR EAX,EAX
|
||||
MOV [EBX],AL
|
||||
MOV EAX,-1
|
||||
MOV ESP,EBP
|
||||
POP EBP
|
||||
RET
|
||||
_0_2:
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
XOR EAX,EAX
|
||||
MOV [EBX],EAX
|
||||
LEA EAX,[EBP-4]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP+8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP+24]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
SHL EAX,1
|
||||
SHL EAX,1
|
||||
ADD EAX,EBX
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
MOV [EBX],EAX
|
||||
_0_4:
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP+16]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
CALL __lt
|
||||
OR EAX,EAX
|
||||
JNE _0_6
|
||||
JMP _0_5
|
||||
_0_6:
|
||||
LEA EAX,[EBP+20]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
ADD EAX,EBX
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP-4]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
ADD EAX,EBX
|
||||
MOV EBX,EAX
|
||||
MOVSX EAX,BYTE [EBX]
|
||||
POP EBX
|
||||
MOV [EBX],AL
|
||||
OR EAX,EAX
|
||||
JE _0_8
|
||||
JMP _0_7
|
||||
_0_8:
|
||||
JMP _0_5
|
||||
_0_7:
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
INC EAX
|
||||
MOV [EBX],EAX
|
||||
JMP _0_4
|
||||
_0_5:
|
||||
LEA EAX,[EBP+20]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
PUSH EAX
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
POP EBX
|
||||
ADD EAX,EBX
|
||||
MOV EBX,EAX
|
||||
XOR EAX,EAX
|
||||
MOV [EBX],AL
|
||||
LEA EAX,[EBP-8]
|
||||
MOV EBX,EAX
|
||||
MOV EAX, [EBX]
|
||||
MOV ESP,EBP
|
||||
POP EBP
|
||||
RET
|
||||
|
29
programs/develop/scc/GETARG.C
Normal file
29
programs/develop/scc/GETARG.C
Normal file
@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
/*
|
||||
** Get command line argument.
|
||||
** Entry: n = Number of the argument.
|
||||
** s = Destination string pointer.
|
||||
** size = Size of destination string.
|
||||
** argc = Argument count from main().
|
||||
** argv = Argument vector(s) from main().
|
||||
** Returns number of characters moved on success,
|
||||
** else EOF.
|
||||
*/
|
||||
getarg(n,s,size,argc,argv)
|
||||
int n; char *s; int size,argc,argv[];
|
||||
{char *str;
|
||||
int i;
|
||||
|
||||
if(n<0 | n>=argc)
|
||||
{*s=NULL;
|
||||
return EOF;
|
||||
}
|
||||
i=0;
|
||||
str=argv[n];
|
||||
while(i<size)
|
||||
{if((s[i]=str[i])==NULL) break;
|
||||
++i;
|
||||
}
|
||||
s[i]=NULL;
|
||||
return i;
|
||||
}
|
140
programs/develop/scc/INTRINS.ASM
Normal file
140
programs/develop/scc/INTRINS.ASM
Normal file
@ -0,0 +1,140 @@
|
||||
;
|
||||
; Small-C Run Time Library for Win NT
|
||||
;
|
||||
; Nasm version 17/Nov/98 H T Walheim
|
||||
; Revised: 20/Nov/98 HTW [Bugs in switch]
|
||||
;
|
||||
|
||||
_CCARGC:
|
||||
;B+ Ellipses arguments ( ,...)
|
||||
;cl - argument count
|
||||
|
||||
xor eax,eax
|
||||
movzx eax,cl ; No sign-extension
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;B+ Compare
|
||||
|
||||
__ult:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
ja true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__ugt:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jb true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__ule:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jae true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__uge:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jbe true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__eq:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
je true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__ne:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jne true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__lt:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jg true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__gt:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jl true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__le:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jge true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__ge:
|
||||
;B+ ???
|
||||
cmp eax,ebx
|
||||
jle true
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;E:.
|
||||
|
||||
__lneg:
|
||||
;B+ Logical Negate of Primary
|
||||
or eax,eax
|
||||
jnz false
|
||||
true:
|
||||
mov eax,1
|
||||
ret
|
||||
|
||||
false:
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
__switch:
|
||||
;B+ Execute "switch" statement
|
||||
|
||||
;eax - switch value
|
||||
;[esp] - pointer to switch table
|
||||
; dd addr1,value1
|
||||
; ...
|
||||
; dd 0
|
||||
; [jmp default]
|
||||
; continuation
|
||||
;
|
||||
; Revised: 20/Nov/98 [JECXZ needed]
|
||||
|
||||
pop ebx
|
||||
jmp skip
|
||||
back:
|
||||
add ebx,8 ;next case-pair
|
||||
skip:
|
||||
mov ecx,[ebx] ;case-label location (adress)
|
||||
jecxz default
|
||||
cmp eax,[ebx+4] ;test case-value
|
||||
jnz back
|
||||
jmp ecx ;match -- jump to case
|
||||
default:
|
||||
add ebx,4
|
||||
jmp ebx ;jump to default/continuation
|
||||
;E:.
|
2699
programs/develop/scc/LIBSTD.ASM
Normal file
2699
programs/develop/scc/LIBSTD.ASM
Normal file
File diff suppressed because it is too large
Load Diff
440
programs/develop/scc/Libstd.c
Normal file
440
programs/develop/scc/Libstd.c
Normal file
@ -0,0 +1,440 @@
|
||||
#include "stdio.h"
|
||||
#include "clib.h"
|
||||
|
||||
/*
|
||||
** Write string to standard output.
|
||||
*/
|
||||
puts(string) char *string;
|
||||
{fputs(string,stdout);
|
||||
OS_fputc('\n',stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
** reverse string in place
|
||||
*/
|
||||
reverse(s) char *s;
|
||||
{char *j; int c;
|
||||
|
||||
j=s+strlen(s)-1;
|
||||
while(s<j)
|
||||
{c=*s;
|
||||
*s++ =*j;
|
||||
*j-- =c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** copy t to s
|
||||
*/
|
||||
strcpy(s,t) char *s,*t;
|
||||
{char *d;
|
||||
|
||||
d=s;
|
||||
while(*s++ =*t++);
|
||||
return (d);
|
||||
}
|
||||
|
||||
/*
|
||||
** return length of string s (fast version)
|
||||
*/
|
||||
strlen(s) char *s;
|
||||
{char *ptr;
|
||||
|
||||
ptr=s;
|
||||
while(*ptr)
|
||||
{++ptr;
|
||||
}
|
||||
|
||||
return (ptr-s);
|
||||
|
||||
#ifdef _INASM
|
||||
#asm
|
||||
xor al,al ; set search value to zero
|
||||
mov cx,65535 ; set huge maximum
|
||||
mov di,[bp+4] ; get address of s
|
||||
cld ; set direction flag forward
|
||||
repne scasb ; scan for zero
|
||||
mov ax,65534
|
||||
sub ax,cx ; calc and return length
|
||||
#endasm
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** return upper-case of c if it is lower-case, else c
|
||||
*/
|
||||
toupper(c) int c;
|
||||
{if(c<='z' && c>='a') return (c-32);
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
** atoi(s) - convert s to integer.
|
||||
*/
|
||||
atoi(s) char *s;
|
||||
{int sign,n;
|
||||
|
||||
while(isspace(*s)) ++s;
|
||||
sign = 1;
|
||||
switch(*s)
|
||||
{case '-': sign=-1;
|
||||
case '+': ++s;
|
||||
}
|
||||
n=0;
|
||||
while(isdigit(*s)) n=10*n+*s++ -'0';
|
||||
return (sign*n);
|
||||
}
|
||||
|
||||
/*
|
||||
** atoib(s,b) - Convert s to "unsigned" integer in base b.
|
||||
** NOTE: This is a non-standard function.
|
||||
*/
|
||||
atoib(s,b) char *s; int b;
|
||||
{int n, digit;
|
||||
|
||||
n=0;
|
||||
while(isspace(*s)) ++s;
|
||||
while((digit=(127 & *s++))>='0')
|
||||
{ if(digit>='a') digit-=87;
|
||||
else if(digit>='A') digit-=55;
|
||||
else digit -= '0';
|
||||
if(digit>=b) break;
|
||||
n=b*n+digit;
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Gets an entire string (including its newline
|
||||
** terminator) or size-1 characters, whichever comes
|
||||
** first. The input is terminated by a null character.
|
||||
** Entry: str = Pointer to destination buffer.
|
||||
** size = Size of the destination buffer.
|
||||
** fd = File descriptor of pertinent file.
|
||||
** Returns str on success, else NULL.
|
||||
*/
|
||||
fgets(str,size,fd) char *str; unsigned size,fd;
|
||||
{return (_gets(str,size,fd,1));
|
||||
}
|
||||
|
||||
/*
|
||||
** Gets an entire string from stdin (excluding its newline
|
||||
** terminator) or size-1 characters, whichever comes
|
||||
** first. The input is terminated by a null character.
|
||||
** The user buffer must be large enough to hold the data.
|
||||
** Entry: str = Pointer to destination buffer.
|
||||
** Returns str on success, else NULL.
|
||||
*/
|
||||
gets(str) char *str;
|
||||
{return (_gets(str,32767,stdin,0));
|
||||
}
|
||||
|
||||
_gets(str,size,fd,nl) char *str; unsigned size,fd,nl;
|
||||
{int backup; char *next;
|
||||
|
||||
next=str;
|
||||
while(--size>0)
|
||||
{switch (*next=fgetc(fd))
|
||||
{case EOF:
|
||||
*next=NULL;
|
||||
if(next==str) return (NULL);
|
||||
return (str);
|
||||
|
||||
case '\n':
|
||||
*(next+nl)=NULL;
|
||||
return (str);
|
||||
|
||||
case RUB: /* \b */
|
||||
if(next>str) backup=1;
|
||||
else backup=0;
|
||||
goto backout;
|
||||
|
||||
case WIPE: /* \r */
|
||||
backup=next-str;
|
||||
backout:
|
||||
if(0/*iscons(fd)*/)
|
||||
{++size;
|
||||
while(backup--)
|
||||
{fputs("\b \b",stderr);
|
||||
--next;++size;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
default:
|
||||
++next;
|
||||
}
|
||||
}
|
||||
*next = NULL;
|
||||
return (str);
|
||||
}
|
||||
|
||||
/*
|
||||
** fprintf(fd, ctlstring, arg, arg, ...) - Formatted print.
|
||||
** Operates as described by Kernighan & Ritchie.
|
||||
** b, c, d, o, s, u, and x specifications are supported.
|
||||
** Note: b (binary) is a non-standard extension.
|
||||
*/
|
||||
fprintf(argc) int argc;
|
||||
{int *nxtarg;
|
||||
|
||||
nxtarg=CCARGC()+&argc;
|
||||
return(_print(*(--nxtarg),--nxtarg));
|
||||
}
|
||||
|
||||
/*
|
||||
** printf(ctlstring, arg, arg, ...) - Formatted print.
|
||||
** Operates as described by Kernighan & Ritchie.
|
||||
** b, c, d, o, s, u, and x specifications are supported.
|
||||
** Note: b (binary) is a non-standard extension.
|
||||
*/
|
||||
printf(argc) int argc;
|
||||
{return(_print(stdout,CCARGC()+&argc-1));
|
||||
}
|
||||
|
||||
/*
|
||||
** _print(fd, ctlstring, arg, arg, ...)
|
||||
** Called by fprintf() and printf().
|
||||
*/
|
||||
_print(fd,nxtarg) int fd,*nxtarg;
|
||||
{int arg,left,pad,cc,len,maxchr,width;
|
||||
char *ctl,*sptr,str[17];
|
||||
|
||||
cc=0;
|
||||
ctl=*nxtarg--;
|
||||
while(*ctl)
|
||||
{if(*ctl!='%') {OS_fputc(*ctl++,fd); ++cc; continue;}
|
||||
else ++ctl;
|
||||
if(*ctl=='%') {OS_fputc(*ctl++,fd); ++cc; continue;}
|
||||
if(*ctl=='-') {left=1; ++ctl;} else left=0;
|
||||
if(*ctl=='0') pad='0';
|
||||
else pad=' ';
|
||||
if(isdigit(*ctl))
|
||||
{width=atoi(ctl++);
|
||||
while(isdigit(*ctl)) ++ctl;
|
||||
}else width=0;
|
||||
if(*ctl=='.')
|
||||
{maxchr=atoi(++ctl);
|
||||
while(isdigit(*ctl)) ++ctl;
|
||||
}else maxchr=0;
|
||||
arg=*nxtarg--;
|
||||
sptr=str;
|
||||
switch(*ctl++)
|
||||
{case 'c': str[0]=arg; str[1]=NULL; break;
|
||||
case 's': sptr=arg; break;
|
||||
case 'd': itoa(arg,str); break;
|
||||
case 'b': itoab(arg,str,2); break;
|
||||
case 'o': itoab(arg,str,8); break;
|
||||
case 'u': itoab(arg,str,10); break;
|
||||
case 'x': itoab(arg,str,16); break;
|
||||
default: return (cc);
|
||||
}
|
||||
len=strlen(sptr);
|
||||
if(maxchr && maxchr<len) len=maxchr;
|
||||
if(width>len) width=width-len; else width=0;
|
||||
if(!left) while(width--) {OS_fputc(pad,fd); ++cc;}
|
||||
while(len--) {OS_fputc(*sptr++,fd); ++cc;}
|
||||
if(left) while(width--) {OS_fputc(pad,fd); ++cc;}
|
||||
}
|
||||
return (cc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Write a string to fd.
|
||||
** Entry: string = Pointer to null-terminated string.
|
||||
** fd = File descriptor of pertinent file.
|
||||
*/
|
||||
fputs(string,fd) char *string; int fd;
|
||||
{while(*string)
|
||||
OS_fputc(*string++,fd);
|
||||
}
|
||||
|
||||
/*
|
||||
** All character classification functions except isascii().
|
||||
** Integer argument (c) must be in ASCII range (0-127) for
|
||||
** dependable answers.
|
||||
*/
|
||||
|
||||
#define ALNUM 1
|
||||
#define ALPHA 2
|
||||
#define CNTRL 4
|
||||
#define DIGIT 8
|
||||
#define GRAPH 16
|
||||
#define LOWER 32
|
||||
#define PRINT 64
|
||||
#define PUNCT 128
|
||||
#define BLANK 256
|
||||
#define UPPER 512
|
||||
#define XDIGIT 1024
|
||||
|
||||
int _is[128] =
|
||||
{0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
||||
0x004, 0x104, 0x104, 0x104, 0x104, 0x104, 0x004, 0x004,
|
||||
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
||||
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
|
||||
0x140, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
|
||||
0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
|
||||
0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
|
||||
0x459, 0x459, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
|
||||
0x0D0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
|
||||
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
|
||||
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
|
||||
0x253, 0x253, 0x253, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x0D0,
|
||||
0x0D0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
|
||||
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
|
||||
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
|
||||
0x073, 0x073, 0x073, 0x0D0, 0x0D0, 0x0D0, 0x0D0, 0x004
|
||||
};
|
||||
|
||||
isalnum (c) int c; {return (_is[c] & ALNUM );} /* 'a'-'z', 'A'-'Z', '0'-'9' */
|
||||
isalpha (c) int c; {return (_is[c] & ALPHA );} /* 'a'-'z', 'A'-'Z' */
|
||||
iscntrl (c) int c; {return (_is[c] & CNTRL );} /* 0-31, 127 */
|
||||
isdigit (c) int c; {return (_is[c] & DIGIT );} /* '0'-'9' */
|
||||
isgraph (c) int c; {return (_is[c] & GRAPH );} /* '!'-'~' */
|
||||
islower (c) int c; {return (_is[c] & LOWER );} /* 'a'-'z' */
|
||||
isprint (c) int c; {return (_is[c] & PRINT );} /* ' '-'~' */
|
||||
ispunct (c) int c; {return (_is[c] & PUNCT );} /* !alnum && !cntrl && !space */
|
||||
isspace (c) int c; {return (_is[c] & BLANK );} /* HT, LF, VT, FF, CR, ' ' */
|
||||
isupper (c) int c; {return (_is[c] & UPPER );} /* 'A'-'Z' */
|
||||
isxdigit(c) int c; {return (_is[c] & XDIGIT);} /* '0'-'9', 'a'-'f', 'A'-'F' */
|
||||
|
||||
/*
|
||||
** itoa(n,s) - Convert n to characters in s
|
||||
*/
|
||||
itoa(n,s) char *s; int n;
|
||||
{int sign;
|
||||
char *ptr;
|
||||
|
||||
ptr=s;
|
||||
if((sign=n)<0) n=-n;
|
||||
do
|
||||
{*ptr++ =n%10+'0';
|
||||
}while((n=n/10)>0);
|
||||
if(sign<0) *ptr++='-';
|
||||
*ptr='\0';
|
||||
reverse(s);
|
||||
}
|
||||
|
||||
/*
|
||||
** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b.
|
||||
** NOTE: This is a non-standard function.
|
||||
*/
|
||||
itoab(n,s,b) int n; char *s; int b;
|
||||
{char *ptr;
|
||||
int lowbit;
|
||||
ptr=s;
|
||||
b >>= 1;
|
||||
do
|
||||
{lowbit=n&1;
|
||||
n=(n>>1)&32767;
|
||||
*ptr=((n%b)<<1)+lowbit;
|
||||
if(*ptr<10) *ptr+='0';
|
||||
else *ptr+=55;
|
||||
++ptr;
|
||||
}while(n/=b);
|
||||
*ptr=0;
|
||||
reverse(s);
|
||||
}
|
||||
|
||||
/*
|
||||
** itod -- convert nbr to signed decimal string of width sz
|
||||
** right adjusted, blank filled; returns str
|
||||
**
|
||||
** if sz > 0 terminate with null byte
|
||||
** if sz = 0 find end of string
|
||||
** if sz < 0 use last byte for data
|
||||
*/
|
||||
itod(nbr,str,sz) int nbr; char str[]; int sz;
|
||||
{char sgn;
|
||||
|
||||
if(nbr<0) {nbr=-nbr; sgn='-';}
|
||||
else sgn=' ';
|
||||
if(sz>0) str[--sz]=NULL;
|
||||
else if(sz<0) sz=-sz;
|
||||
else while(str[sz]!=NULL) ++sz;
|
||||
while(sz)
|
||||
{str[--sz]=(nbr%10+'0');
|
||||
if((nbr=nbr/10)==0) break;
|
||||
}
|
||||
if(sz) str[--sz]=sgn;
|
||||
while(sz>0) str[--sz]=' ';
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
** itoo -- converts nbr to octal string of length sz
|
||||
** right adjusted and blank filled, returns str
|
||||
**
|
||||
** if sz > 0 terminate with null byte
|
||||
** if sz = 0 find end of string
|
||||
** if sz < 0 use last byte for data
|
||||
*/
|
||||
itoo(nbr,str,sz) int nbr; char str[]; int sz;
|
||||
{int digit;
|
||||
|
||||
if(sz>0) str[--sz]=0;
|
||||
else if(sz<0) sz=-sz;
|
||||
else while(str[sz]!=0) ++sz;
|
||||
while(sz)
|
||||
{digit=nbr&7;nbr=(nbr>>3)&8191;
|
||||
str[--sz]=digit+48;
|
||||
if(nbr==0) break;
|
||||
}
|
||||
while(sz) str[--sz]=' ';
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
** itou -- convert nbr to unsigned decimal string of width sz
|
||||
** right adjusted, blank filled; returns str
|
||||
**
|
||||
** if sz > 0 terminate with null byte
|
||||
** if sz = 0 find end of string
|
||||
** if sz < 0 use last byte for data
|
||||
*/
|
||||
itou(nbr,str,sz) int nbr; char str[]; int sz;
|
||||
{int lowbit;
|
||||
|
||||
if(sz>0) str[--sz]=NULL;
|
||||
else if(sz<0) sz=-sz;
|
||||
else while(str[sz]!=NULL) ++sz;
|
||||
while(sz)
|
||||
{lowbit=nbr&1;
|
||||
nbr=(nbr>>1)&32767; /* divide by 2 */
|
||||
str[--sz]=((nbr%5)<<1)+lowbit+'0';
|
||||
if((nbr=nbr/5)==0) break;
|
||||
}
|
||||
while(sz) str[--sz]=' ';
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
** itox -- converts nbr to hex string of length sz
|
||||
** right adjusted and blank filled, returns str
|
||||
**
|
||||
** if sz > 0 terminate with null byte
|
||||
** if sz = 0 find end of string
|
||||
** if sz < 0 use last byte for data
|
||||
*/
|
||||
|
||||
itox(nbr,str,sz) int nbr; char str[]; int sz;
|
||||
{int digit,offset;
|
||||
|
||||
if(sz>0) str[--sz]=0;
|
||||
else if(sz<0) sz=-sz;
|
||||
else while(str[sz]!=0) ++sz;
|
||||
while(sz)
|
||||
{digit=nbr&15;
|
||||
nbr=nbr/16;
|
||||
/*
|
||||
nbr=(nbr>>4)&4095; // 268435455; // 0xFFFFFFF
|
||||
*/
|
||||
if(digit<10) offset=48;
|
||||
else offset=55;
|
||||
str[--sz]=digit+offset;
|
||||
if(nbr==0) break;
|
||||
}
|
||||
while(sz) str[--sz]=' ';
|
||||
return str;
|
||||
}
|
||||
|
268
programs/develop/scc/MACROS.INC
Normal file
268
programs/develop/scc/MACROS.INC
Normal file
@ -0,0 +1,268 @@
|
||||
; new application structure
|
||||
macro meos_app_start
|
||||
{
|
||||
use32
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01'
|
||||
dd 0x01
|
||||
dd __start
|
||||
dd __end
|
||||
dd __memory
|
||||
dd __stack
|
||||
|
||||
if used __params & ~defined __params
|
||||
dd __params
|
||||
else
|
||||
dd 0x0
|
||||
end if
|
||||
|
||||
dd 0x0
|
||||
}
|
||||
MEOS_APP_START fix meos_app_start
|
||||
|
||||
macro code
|
||||
{
|
||||
__start:
|
||||
}
|
||||
CODE fix code
|
||||
|
||||
macro data
|
||||
{
|
||||
__data:
|
||||
}
|
||||
DATA fix data
|
||||
|
||||
macro udata
|
||||
{
|
||||
if used __params & ~defined __params
|
||||
__params:
|
||||
db 0
|
||||
__end:
|
||||
rb 255
|
||||
else
|
||||
__end:
|
||||
end if
|
||||
__udata:
|
||||
}
|
||||
UDATA fix udata
|
||||
|
||||
macro meos_app_end
|
||||
{
|
||||
align 32
|
||||
rb 2048
|
||||
__stack:
|
||||
__memory:
|
||||
}
|
||||
MEOS_APP_END fix meos_app_end
|
||||
|
||||
|
||||
; macro for defining multiline text data
|
||||
struc mstr [sstring]
|
||||
{
|
||||
forward
|
||||
local ssize
|
||||
virtual at 0
|
||||
db sstring
|
||||
ssize = $
|
||||
end virtual
|
||||
dd ssize
|
||||
db sstring
|
||||
common
|
||||
dd -1
|
||||
}
|
||||
|
||||
|
||||
; strings
|
||||
macro sz name,[data] { ; from MFAR [mike.dld]
|
||||
common
|
||||
if used name
|
||||
label name
|
||||
end if
|
||||
forward
|
||||
if used name
|
||||
db data
|
||||
end if
|
||||
common
|
||||
if used name
|
||||
.size = $-name
|
||||
end if
|
||||
}
|
||||
|
||||
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
|
||||
common
|
||||
if used name
|
||||
label name
|
||||
end if
|
||||
forward
|
||||
if (used name)&(lang eq lng)
|
||||
db data
|
||||
end if
|
||||
common
|
||||
if used name
|
||||
.size = $-name
|
||||
end if
|
||||
}
|
||||
|
||||
|
||||
|
||||
; easy system call macro
|
||||
macro mpack dest, hsrc, lsrc
|
||||
{
|
||||
if (hsrc eqtype 0) & (lsrc eqtype 0)
|
||||
mov dest, (hsrc) shl 16 + lsrc
|
||||
else
|
||||
if (hsrc eqtype 0) & (~lsrc eqtype 0)
|
||||
mov dest, (hsrc) shl 16
|
||||
add dest, lsrc
|
||||
else
|
||||
mov dest, hsrc
|
||||
shl dest, 16
|
||||
add dest, lsrc
|
||||
end if
|
||||
end if
|
||||
}
|
||||
|
||||
macro __mov reg,a,b { ; mike.dld
|
||||
if (~a eq)&(~b eq)
|
||||
mpack reg,a,b
|
||||
else if (~a eq)&(b eq)
|
||||
mov reg,a
|
||||
end if
|
||||
}
|
||||
|
||||
macro mcall a,b,c,d,e,f { ; mike.dld
|
||||
__mov eax,a
|
||||
__mov ebx,b
|
||||
__mov ecx,c
|
||||
__mov edx,d
|
||||
__mov esi,e
|
||||
__mov edi,f
|
||||
int 0x40
|
||||
}
|
||||
|
||||
|
||||
|
||||
; language for programs
|
||||
lang fix ru ; ru en fr ge fi
|
||||
|
||||
|
||||
|
||||
; optimize the code for size
|
||||
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
|
||||
|
||||
macro add arg1,arg2
|
||||
{
|
||||
if (arg2 eqtype 0)
|
||||
if (arg2) = 1
|
||||
inc arg1
|
||||
else
|
||||
add arg1,arg2
|
||||
end if
|
||||
else
|
||||
add arg1,arg2
|
||||
end if
|
||||
}
|
||||
|
||||
macro sub arg1,arg2
|
||||
{
|
||||
if (arg2 eqtype 0)
|
||||
if (arg2) = 1
|
||||
dec arg1
|
||||
else
|
||||
sub arg1,arg2
|
||||
end if
|
||||
else
|
||||
sub arg1,arg2
|
||||
end if
|
||||
}
|
||||
|
||||
macro mov arg1,arg2
|
||||
{
|
||||
if (arg1 in __regs) & (arg2 eqtype 0)
|
||||
if (arg2) = 0
|
||||
xor arg1,arg1
|
||||
else if (arg2) = 1
|
||||
xor arg1,arg1
|
||||
inc arg1
|
||||
else if (arg2) = -1
|
||||
or arg1,-1
|
||||
else if (arg2) > -128 & (arg2) < 128
|
||||
push arg2
|
||||
pop arg1
|
||||
else
|
||||
mov arg1,arg2
|
||||
end if
|
||||
else
|
||||
mov arg1,arg2
|
||||
end if
|
||||
}
|
||||
|
||||
|
||||
macro struct name
|
||||
{
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.#name = $ - name
|
||||
end virtual
|
||||
}
|
||||
|
||||
; structures used in MeOS
|
||||
struc process_information
|
||||
{
|
||||
.cpu_usage dd ? ; +0
|
||||
.window_stack_position dw ? ; +4
|
||||
.window_stack_value dw ? ; +6
|
||||
.not_used1 dw ? ; +8
|
||||
.process_name rb 12 ; +10
|
||||
.memory_start dd ? ; +22
|
||||
.used_memory dd ? ; +26
|
||||
.PID dd ? ; +30
|
||||
.x_start dd ? ; +34
|
||||
.y_start dd ? ; +38
|
||||
.x_size dd ? ; +42
|
||||
.y_size dd ? ; +46
|
||||
.slot_state dw ? ; +50
|
||||
rb (1024-52)
|
||||
}
|
||||
struct process_information
|
||||
|
||||
struc system_colors
|
||||
{
|
||||
.frame dd ?
|
||||
.grab dd ?
|
||||
.grab_button dd ?
|
||||
.grab_button_text dd ?
|
||||
.grab_text dd ?
|
||||
.work dd ?
|
||||
.work_button dd ?
|
||||
.work_button_text dd ?
|
||||
.work_text dd ?
|
||||
.work_graph dd ?
|
||||
}
|
||||
struct system_colors
|
||||
|
||||
|
||||
; constants
|
||||
|
||||
; events
|
||||
EV_IDLE = 0
|
||||
EV_TIMER = 0
|
||||
EV_REDRAW = 1
|
||||
EV_KEY = 2
|
||||
EV_BUTTON = 3
|
||||
EV_EXIT = 4
|
||||
EV_BACKGROUND = 5
|
||||
EV_MOUSE = 6
|
||||
EV_IPC = 7
|
||||
EV_STACK = 8
|
||||
|
||||
; event mask bits for function 40
|
||||
EVM_REDRAW = 1b
|
||||
EVM_KEY = 10b
|
||||
EVM_BUTTON = 100b
|
||||
EVM_EXIT = 1000b
|
||||
EVM_BACKGROUND = 10000b
|
||||
EVM_MOUSE = 100000b
|
||||
EVM_IPC = 1000000b
|
||||
EVM_STACK = 10000000b
|
6
programs/develop/scc/NOTICE.H
Normal file
6
programs/develop/scc/NOTICE.H
Normal file
@ -0,0 +1,6 @@
|
||||
/*
|
||||
** NOTICE.H -- Small C Signon Notice.
|
||||
*/
|
||||
#define VERSION "Small C 386/NT, Version 3.1, Revision Level 1\n"
|
||||
#define CRIGHT1 "Copyright 1982-1998 J. E. Hendrix H T Walheim\n"
|
||||
#define CRIGHT2 "2008 - port to KolibriOS (jacekm.pl@gmail.com)\n\n"
|
681
programs/develop/scc/OSFUNC.ASM
Normal file
681
programs/develop/scc/OSFUNC.ASM
Normal file
@ -0,0 +1,681 @@
|
||||
include "macros.inc"
|
||||
;
|
||||
; OS function implementation
|
||||
; SmallC for KolibriOS
|
||||
;
|
||||
|
||||
;B+ General definitions
|
||||
|
||||
;B+ File defs
|
||||
;const
|
||||
;param
|
||||
BAD equ -1
|
||||
files equ 100
|
||||
save_buffer equ 0x20000 ;32
|
||||
save_buffer_w equ 0x400000 ;32
|
||||
save_file_name equ 0x20000
|
||||
|
||||
;system
|
||||
EOF equ -1
|
||||
|
||||
;memory
|
||||
fileinfo equ I_END
|
||||
start_data equ (fileinfo+16384)
|
||||
;
|
||||
mem_heap equ 0x100000
|
||||
;
|
||||
g_handle equ 0x300000
|
||||
;dword - pointer - relative to file
|
||||
;dword - begin of file
|
||||
;dword - file size
|
||||
;dword - 0/1 <=> read/write
|
||||
;E:.
|
||||
|
||||
;E:.
|
||||
|
||||
init_osfunc:
|
||||
;B+ Init OS functions
|
||||
;B+ Clear file handles
|
||||
mov edi,g_handle
|
||||
mov ecx,files
|
||||
shl ecx,2 ;*4
|
||||
xor eax,eax
|
||||
cld
|
||||
rep stosd
|
||||
;E:.
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;B+ Main OS functions
|
||||
ppp dd 70
|
||||
|
||||
_OS_fopen:
|
||||
;B+ Implement "fopen"
|
||||
;esp+4 - mode
|
||||
;esp+8 - file name
|
||||
|
||||
; mov eax,-1
|
||||
; int 0x40
|
||||
|
||||
; mov ebx,[esp+8];
|
||||
; push dword 10
|
||||
; push dword [ppp]
|
||||
; push ebx
|
||||
; push dword 12
|
||||
; call _outstrg
|
||||
; add esp,4*4
|
||||
; add [ppp],10
|
||||
|
||||
; cmp byte [ebx+8],0
|
||||
; jne .l
|
||||
; mov byte [ebx+8],'?'
|
||||
;.l:
|
||||
; cmp [ppp],80
|
||||
; je .l
|
||||
|
||||
mov ecx , [esp+4] ; file mode
|
||||
mov [file_mode],ecx
|
||||
;B+ Copy file name
|
||||
|
||||
|
||||
mov esi,[esp+8]
|
||||
mov edi,[p_filename]
|
||||
mov ecx,12
|
||||
.next_copy:
|
||||
lodsb
|
||||
;fill name (space)
|
||||
or al,al
|
||||
jz .fill_space
|
||||
;set upper case
|
||||
cmp al,'a'
|
||||
jb .good_char
|
||||
cmp al,'z'
|
||||
ja .good_char
|
||||
add al,'A'-'a'
|
||||
.good_char:
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .next_copy
|
||||
.fill_space:
|
||||
mov al,' '
|
||||
cld
|
||||
rep stosb
|
||||
|
||||
mov eax,[file_mode]
|
||||
cmp byte [eax],'w'
|
||||
jne .no_wri
|
||||
|
||||
|
||||
;B+ Copy file name
|
||||
mov esi,[esp+8]
|
||||
mov edi,[w_file_name]
|
||||
mov ecx,12
|
||||
.next_copy2:
|
||||
lodsb
|
||||
;fill name (space)
|
||||
or al,al
|
||||
jz .fill_space2
|
||||
;set upper case
|
||||
cmp al,'a'
|
||||
jb .good_char2
|
||||
cmp al,'z'
|
||||
ja .good_char2
|
||||
add al,'A'-'a'
|
||||
.good_char2:
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .next_copy2
|
||||
.fill_space2:
|
||||
mov al,' '
|
||||
cld
|
||||
rep stosb
|
||||
|
||||
.no_wri:
|
||||
|
||||
|
||||
|
||||
;E:.
|
||||
;B+ Find file handle
|
||||
mov eax,g_handle
|
||||
.new_handle:
|
||||
cmp dword [eax+4],0
|
||||
je .find_place
|
||||
add eax,16
|
||||
cmp eax,g_handle+files*16-16
|
||||
jne .new_handle
|
||||
xor eax,eax ; no free handle
|
||||
ret
|
||||
.find_place:
|
||||
; TMP: mov eax,[.ccc]
|
||||
; TMP: add [.ccc],16
|
||||
;E:.
|
||||
push eax
|
||||
;B+ Test open mode
|
||||
mov eax,[esp+4+4]
|
||||
cmp byte [eax],'r'
|
||||
je .open_read
|
||||
cmp byte [eax],'w'
|
||||
je .open_write
|
||||
;bad mode
|
||||
add esp,4
|
||||
mov eax,eax ; invalid open mode
|
||||
ret
|
||||
;E:.
|
||||
|
||||
; TMP:.ccc dd g_handle
|
||||
|
||||
.open_read:
|
||||
;B+ Open for read
|
||||
;B+ Read file
|
||||
|
||||
;Wait to read correct
|
||||
mov ebx,100
|
||||
mov eax,5
|
||||
int 0x40
|
||||
|
||||
mov eax,[g_fileend]
|
||||
mov dword [file_parameters+2*4],2000 ;read all
|
||||
mov dword [file_parameters+3*4],eax
|
||||
|
||||
mov dword [file_parameters],0
|
||||
mov ebx,file_parameters
|
||||
mov eax,58
|
||||
int 0x40
|
||||
;E:.
|
||||
|
||||
;B+ TEST FILE FOUND
|
||||
or eax,eax
|
||||
jz .file_found
|
||||
cmp eax,5
|
||||
je .file_found
|
||||
|
||||
; mov ecx,eax ; eax
|
||||
; mov ebx,8 shl 16 + 0x0100
|
||||
; mov edx,100 shl 16 + 120
|
||||
; mov esi,0xffffff
|
||||
; mov eax,47
|
||||
; int 0x40
|
||||
|
||||
;file not found - return 0
|
||||
add esp,4
|
||||
xor eax,eax
|
||||
ret
|
||||
.file_found:
|
||||
;E:.
|
||||
pop eax
|
||||
push ebx
|
||||
xchg eax,ebx
|
||||
;B+ Fill file handle
|
||||
;save current pointer
|
||||
xor eax,eax
|
||||
mov [ebx],eax
|
||||
|
||||
;save file begin
|
||||
mov eax,[g_fileend]
|
||||
mov [ebx+4],eax
|
||||
|
||||
;save file size
|
||||
pop eax
|
||||
mov [ebx+8],eax
|
||||
;reserve file zone
|
||||
add eax,7
|
||||
and eax,not 7
|
||||
add [g_fileend],eax
|
||||
|
||||
;save file mode
|
||||
mov eax,0 ;read
|
||||
mov [ebx+12],eax
|
||||
;E:.
|
||||
xchg eax,ebx ;return pointer place
|
||||
ret
|
||||
;E:.
|
||||
|
||||
.open_write:
|
||||
;B+ Open for write
|
||||
;B+ Reserve filename
|
||||
|
||||
; p_filename -> w_file_name
|
||||
|
||||
;pusha
|
||||
; mov eax, w_file_name
|
||||
; mov ebx, [p_filename]
|
||||
;.ncpy:
|
||||
; mov ch, byte [ebx]
|
||||
; cmp ch, 0
|
||||
; je .ecpy
|
||||
; mov [eax], ch
|
||||
; inc dword [eax]
|
||||
; inc dword [ebx]
|
||||
;jmp .ncpy
|
||||
;
|
||||
;.ecpy:
|
||||
;
|
||||
;popa
|
||||
|
||||
mov [save_buffer_p], save_buffer_w
|
||||
|
||||
mov esi,[p_filename]
|
||||
mov edi,[g_fileend]
|
||||
mov ecx,12
|
||||
cld
|
||||
rep movsb
|
||||
add [g_fileend],16
|
||||
;E:.
|
||||
pop ebx
|
||||
;B+ Fill file handle
|
||||
;save begin pointer
|
||||
xor eax,eax
|
||||
mov [ebx],eax
|
||||
|
||||
;save file begin
|
||||
mov eax,[g_fileend]
|
||||
mov [ebx+4],eax
|
||||
|
||||
;save file zone
|
||||
mov dword [ebx+8],save_buffer
|
||||
;reserve file zone
|
||||
add [g_fileend],save_buffer
|
||||
|
||||
;save file mode
|
||||
mov eax,1 ;write
|
||||
mov [ebx+12],eax
|
||||
;E:.
|
||||
xchg eax,ebx ;return pointer place
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;E:.
|
||||
|
||||
_OS_fclos:
|
||||
;B+ Close file
|
||||
;esp+4 - file handle
|
||||
|
||||
;B+ Test write mode - save file
|
||||
mov eax,[esp+4]
|
||||
mov eax,[eax+12]
|
||||
cmp eax,1
|
||||
;E:.
|
||||
jne .no_write
|
||||
|
||||
mov eax, [esp+4]
|
||||
mov ecx, [eax]
|
||||
mov ebx, [eax+8]
|
||||
|
||||
mov ebx, [save_buffer_p]
|
||||
sub ebx, save_buffer_w
|
||||
; ebx = number of read bytes = file size
|
||||
; save loaded file
|
||||
mov [dest_info.bytes],ebx ; file size in bytes
|
||||
|
||||
mov [dest_info.bytes+4], save_buffer_w
|
||||
;mov eax, [p_filename];[w_file_name]
|
||||
;mov [destination],eax
|
||||
mov eax,70
|
||||
mov ebx,dest_info
|
||||
mcall
|
||||
|
||||
; check if 58 function failed
|
||||
test eax,eax
|
||||
je .ok_write
|
||||
add eax,7 ; error number += 7
|
||||
cmp eax,6+7
|
||||
jna .copy_error
|
||||
mov eax,7+7
|
||||
jmp .copy_error
|
||||
|
||||
.copy_error:
|
||||
.ok_write:
|
||||
|
||||
|
||||
;E:.
|
||||
jmp .read
|
||||
|
||||
.no_write:
|
||||
;B+ Test read mode - if no error end
|
||||
cmp eax,0
|
||||
je .read
|
||||
mov eax,BAD
|
||||
ret
|
||||
;E:.
|
||||
.read:
|
||||
|
||||
;B+ Relace memory
|
||||
;find file size
|
||||
mov eax,[esp+4]
|
||||
mov ecx,[eax+8]
|
||||
add ecx,7
|
||||
and ecx,not 7
|
||||
push ecx
|
||||
|
||||
;mov memory
|
||||
mov esi,[eax+4]
|
||||
mov edi,esi
|
||||
add esi,ecx
|
||||
mov ecx,[g_fileend]
|
||||
sub ecx,edi
|
||||
jz .is_last
|
||||
shr ecx,2
|
||||
inc ecx ;not neccessery
|
||||
cld
|
||||
rep movsd
|
||||
;update gl. memory
|
||||
.is_last:
|
||||
pop ecx
|
||||
sub dword [g_fileend],ecx
|
||||
|
||||
;update file pointers
|
||||
mov edx,ecx
|
||||
mov ecx,[eax+4]
|
||||
mov eax,g_handle
|
||||
.new_handle1:
|
||||
mov ebx,[eax+4]
|
||||
cmp ebx,ecx
|
||||
jbe .no_update
|
||||
sub ebx,edx
|
||||
mov [eax+4],ebx
|
||||
.no_update:
|
||||
add eax,16
|
||||
cmp eax,g_handle+files*16
|
||||
jne .new_handle1
|
||||
|
||||
;clear handle
|
||||
mov edi,[esp+4]
|
||||
xor eax,eax
|
||||
cld
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
;E:.
|
||||
ret
|
||||
;E:.
|
||||
|
||||
_OS_fgetc:
|
||||
;B+ Load char from file
|
||||
;esp+4 - input file
|
||||
|
||||
mov eax,[esp+4]
|
||||
mov ebx,[eax]
|
||||
cmp ebx,[eax+8]
|
||||
je .eof
|
||||
inc dword [eax]
|
||||
add ebx,[eax+4]
|
||||
movzx eax,byte [ebx]
|
||||
ret
|
||||
.eof:
|
||||
mov eax,EOF
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;rrr db 'g',0
|
||||
|
||||
_OS_fputc:
|
||||
;B+ Save char to file
|
||||
;esp+4 - output file
|
||||
;esp+8 - char to write
|
||||
|
||||
;push dword '<'
|
||||
;mov cl,1
|
||||
;push dword 0
|
||||
;call test_outch
|
||||
;add esp,8
|
||||
|
||||
|
||||
|
||||
;B+ Temp - write direct.
|
||||
cmp dword [esp+4],__iob
|
||||
jne .real_write0
|
||||
jmp _OS_exit
|
||||
.real_write0:
|
||||
cmp dword [esp+4],__iob+32
|
||||
jne .real_write1
|
||||
mov [print_textcolor],0x00ffff
|
||||
jmp test_outch
|
||||
.real_write1:
|
||||
cmp dword [esp+4],__iob+64
|
||||
jne .real_write2
|
||||
mov [print_textcolor],0x77ffff
|
||||
jmp test_outch
|
||||
.real_write2:
|
||||
;E:.
|
||||
|
||||
mov ebx,[save_buffer_p]
|
||||
mov eax,[esp+8]
|
||||
mov [ebx],eax
|
||||
inc dword [save_buffer_p]
|
||||
|
||||
|
||||
ret
|
||||
|
||||
;push dword '<'
|
||||
;mov cl,1
|
||||
;push dword 0
|
||||
;call test_outch
|
||||
;add esp,8
|
||||
|
||||
mov eax,[esp+4]
|
||||
mov ebx,[eax]
|
||||
push ebx
|
||||
cmp ebx,[eax+8]
|
||||
jne .write_normal
|
||||
|
||||
|
||||
|
||||
;B+ Alloc save_buffer bytes
|
||||
;mov memory
|
||||
mov ebx,[esp+4+4]
|
||||
mov esi,[g_fileend]
|
||||
mov edi,esi
|
||||
add edi,save_buffer-4
|
||||
mov ecx,esi
|
||||
sub ecx,[ebx+4]
|
||||
sub ecx,[ebx+8]
|
||||
shr ecx,2
|
||||
jz .is_last
|
||||
sub esi,4
|
||||
std
|
||||
rep movsd
|
||||
.is_last:
|
||||
|
||||
;expand file size
|
||||
add dword [eax+8],save_buffer
|
||||
|
||||
;update file pointers
|
||||
mov ebx,g_handle
|
||||
.new_handle:
|
||||
mov ecx,[ebx+4]
|
||||
cmp [eax+4],ecx
|
||||
jae .no_update
|
||||
add dword [ebx+4],save_buffer
|
||||
.no_update:
|
||||
add ebx,16
|
||||
cmp ebx,g_handle+files*16-16
|
||||
jne .new_handle
|
||||
;E:.
|
||||
|
||||
.write_normal:
|
||||
pop ebx
|
||||
inc dword [eax]
|
||||
add ebx,[eax+4]
|
||||
mov cl,[esp+8]
|
||||
mov byte [ebx],cl
|
||||
|
||||
;sub [test_outch.x_coord],2
|
||||
;
|
||||
;push dword '>'
|
||||
;mov cl,1
|
||||
;push dword 0
|
||||
;call test_outch
|
||||
;add esp,8
|
||||
;
|
||||
;sub [test_outch.x_coord],6
|
||||
|
||||
xor eax,eax
|
||||
ret
|
||||
;E:.
|
||||
|
||||
_OS_callo:
|
||||
;B+ Alloc memory
|
||||
;find all size
|
||||
mov eax,[esp+4]
|
||||
mov ebx,[esp+8]
|
||||
mul ebx
|
||||
push eax
|
||||
|
||||
;clear memory
|
||||
mov edi,[.mem_p]
|
||||
xor eax,eax
|
||||
mov ecx,[esp]
|
||||
cld
|
||||
rep stosb
|
||||
|
||||
;update new memory pointer
|
||||
pop ebx
|
||||
push dword [.mem_p]
|
||||
add ebx,7
|
||||
and ebx,not 7
|
||||
add [.mem_p],ebx
|
||||
|
||||
;return value
|
||||
pop eax
|
||||
ret
|
||||
|
||||
.mem_p dd mem_heap
|
||||
;E:.
|
||||
|
||||
_OS_exit:
|
||||
;B+ Exit program
|
||||
; ;TMP
|
||||
; mov eax,-1
|
||||
; int 0x40
|
||||
mov esp,[exit_esp]
|
||||
sub esp,4
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;E:.
|
||||
|
||||
|
||||
|
||||
|
||||
;B+ Test procedures
|
||||
|
||||
;B+ Definitions
|
||||
LEFTMARGIN equ 11
|
||||
BEGIN_CHARS equ 20
|
||||
NL equ 10
|
||||
;E:.
|
||||
|
||||
print_textcolor dd 0x00ffff
|
||||
|
||||
_file_beg:
|
||||
;B+ Show begin of file - test fopen
|
||||
;esp+4 - file handle (descriptor)
|
||||
|
||||
mov eax,[esp+4]
|
||||
mov ebx,10 shl 16 + 30
|
||||
mov ecx,[print_textcolor]
|
||||
mov edx,[eax+4]
|
||||
mov esi,BEGIN_CHARS
|
||||
mov eax,4
|
||||
int 0x40
|
||||
ret
|
||||
;E:.
|
||||
|
||||
_outstrg:
|
||||
;B+ Draw black text - test function call
|
||||
;esp+4*4 - x
|
||||
;esp+4*3 - y
|
||||
;esp+4*2 - *c
|
||||
;esp+4*1 - len
|
||||
|
||||
mov ebx,[esp+4*4]
|
||||
shl ebx,16
|
||||
mov bx,[esp+4*3]
|
||||
mov ecx,[print_textcolor]
|
||||
mov edx,[esp+4*2]
|
||||
mov esi,[esp+4]
|
||||
mov eax,4
|
||||
int 0x40
|
||||
ret
|
||||
;E:.
|
||||
|
||||
test_outch:
|
||||
;B+ Draw one char - use as _OS_fputc, to test printf(...)
|
||||
;esp+8 - char to write
|
||||
|
||||
;this is test! \b \r - not nesessary
|
||||
|
||||
mov al,[esp+8]
|
||||
cmp al,NL
|
||||
jne .no_newline
|
||||
add [.y_coord],10
|
||||
mov [.x_coord],LEFTMARGIN
|
||||
ret
|
||||
.no_newline:
|
||||
|
||||
mov ebx,[.x_coord]
|
||||
shl ebx,16
|
||||
mov bx,word [.y_coord]
|
||||
mov ecx,[print_textcolor]
|
||||
mov [.out_char],al
|
||||
mov edx,.out_char
|
||||
mov esi,1
|
||||
mov eax,4
|
||||
int 0x40
|
||||
|
||||
add [.x_coord],6
|
||||
;mov eax,5
|
||||
;mov ebx,5
|
||||
;int 0x40
|
||||
ret
|
||||
|
||||
.x_coord dd LEFTMARGIN
|
||||
.y_coord dd 60
|
||||
.out_char db 0
|
||||
;E:.
|
||||
|
||||
;E:.
|
||||
|
||||
;B+ Data section
|
||||
;B+ Memory managment
|
||||
g_fileend dd g_handle+files*4*4 ;from 2MB+100*4*4
|
||||
;w_buff dd
|
||||
;E:.
|
||||
|
||||
save_buffer_p dd save_buffer_w
|
||||
;B+ File parameters
|
||||
file_parameters:
|
||||
dd 0x0 ; mode
|
||||
dd 0x0 ; first block
|
||||
dd 1000 ; block read
|
||||
dd -1 ; return place
|
||||
dd fileinfo ; work area
|
||||
filepath: times 100 db 0
|
||||
|
||||
file_mode dd 0 ;file mode
|
||||
|
||||
dest_info: ; DESTINATION FILEINFO
|
||||
dd 2
|
||||
dd 0
|
||||
dd 0
|
||||
.bytes dd ?
|
||||
dd save_buffer
|
||||
db 0
|
||||
destination:
|
||||
dd save_file_name
|
||||
;db "EXAMPLE.ASM",0
|
||||
|
||||
|
||||
|
||||
w_file_name dd save_file_name
|
||||
|
||||
p_filename dd 0x0
|
||||
;E:.
|
||||
;E:.
|
||||
|
||||
;TO DO
|
||||
mov eax,-1
|
||||
int 0x40
|
||||
;TO DO
|
||||
|
18
programs/develop/scc/README.TXT
Normal file
18
programs/develop/scc/README.TXT
Normal file
@ -0,0 +1,18 @@
|
||||
##############################
|
||||
# SCC (simple c compiler)
|
||||
# port of CCOMP to KolibriOS
|
||||
#
|
||||
######
|
||||
# contact: jacekm.pl@gmail.com
|
||||
##############################
|
||||
|
||||
KNOWN BUGS:
|
||||
* only directiory /rd/1/ works
|
||||
|
||||
HISTORY:
|
||||
* 0.5.3:
|
||||
- output dir fixed
|
||||
* 0.5.2:
|
||||
- static output file
|
||||
* 0.5.1:
|
||||
- first realase
|
392
programs/develop/scc/SCC.ASM
Normal file
392
programs/develop/scc/SCC.ASM
Normal file
@ -0,0 +1,392 @@
|
||||
;
|
||||
; Port to KolibliOS
|
||||
; (jacekm.pl@gmail.com)
|
||||
;
|
||||
|
||||
;B+ System header
|
||||
use32
|
||||
org 0x0
|
||||
db 'MENUET01'
|
||||
dd 0x01
|
||||
dd START
|
||||
dd I_END
|
||||
dd 0x500000
|
||||
dd 0x7fff0
|
||||
dd 0x0,0x0
|
||||
;E:.
|
||||
|
||||
;B+ Include C files
|
||||
; Compiler tools
|
||||
include "INTRINS.ASM"
|
||||
|
||||
; C Library ("stdio.asm")
|
||||
include "LIBSTD.ASM"
|
||||
|
||||
; MenuetOS implement
|
||||
include "OSFUNC.ASM"
|
||||
|
||||
_fopen equ _OS_fopen
|
||||
_fputc equ _OS_fputc
|
||||
_fgetc equ _OS_fgetc
|
||||
_fclose equ _OS_fclos
|
||||
|
||||
;Main program (compiled from C)
|
||||
include "GETARG.ASM"
|
||||
include "CC1.ASM"
|
||||
include "CC2.ASM"
|
||||
include "CC3.ASM"
|
||||
include "CC4.ASM"
|
||||
;E:.
|
||||
|
||||
START:
|
||||
;B+ Main cycle
|
||||
call draw_window
|
||||
still:
|
||||
mov eax,10
|
||||
int 0x40
|
||||
still1:
|
||||
|
||||
cmp eax,1
|
||||
je red
|
||||
cmp eax,2
|
||||
je key
|
||||
cmp eax,3
|
||||
je button
|
||||
jmp still
|
||||
|
||||
red:
|
||||
call draw_window
|
||||
jmp still
|
||||
|
||||
key:
|
||||
mov eax,2
|
||||
int 0x40
|
||||
jmp still
|
||||
|
||||
button:
|
||||
mov eax,17
|
||||
int 0x40
|
||||
|
||||
cmp ah,1
|
||||
jne .noclose
|
||||
mov eax,-1
|
||||
int 0x40
|
||||
.noclose:
|
||||
|
||||
cmp ah,2
|
||||
jne .no_run
|
||||
; call begin_osfunc
|
||||
;B+ Copy file path
|
||||
mov esi,inp_path
|
||||
mov edi,filepath
|
||||
mov ecx,[p_len]
|
||||
push ecx
|
||||
cld
|
||||
rep movsb
|
||||
pop ecx
|
||||
add ecx,filepath
|
||||
mov [p_filename],ecx
|
||||
;E:.
|
||||
;B+ Clear word area
|
||||
mov ebx,10 shl 16 + 280
|
||||
mov ecx,60 shl 16 + 250
|
||||
mov edx,0x303030
|
||||
mov eax,13
|
||||
int 0x40
|
||||
;E:.
|
||||
;B+ Init parameters
|
||||
mov ecx,_input
|
||||
sub ecx,_nogo
|
||||
mov edi,_nogo
|
||||
xor eax,eax
|
||||
cld
|
||||
rep stosb
|
||||
mov [_input],-1
|
||||
mov [_input2],-1
|
||||
mov [_usexpr],1
|
||||
mov [_ccode],1
|
||||
mov [_quote],34
|
||||
mov [test_outch.y_coord],60
|
||||
;E:.
|
||||
call init_osfunc
|
||||
push dword 4
|
||||
push args
|
||||
;B+ Save exit ESP
|
||||
mov [exit_esp],esp
|
||||
;E:.
|
||||
call _main
|
||||
add esp,8
|
||||
; call end_osfunc
|
||||
.no_run:
|
||||
|
||||
cmp ah,3
|
||||
jne .no_path
|
||||
mov eax,inp_path
|
||||
mov bx,27
|
||||
call read_string
|
||||
mov edx,[r_pos]
|
||||
mov [p_len],edx
|
||||
;
|
||||
cmp ah,10
|
||||
je still
|
||||
jmp still1
|
||||
.no_path:
|
||||
|
||||
cmp ah,4
|
||||
jne .no_file
|
||||
mov eax,inp_file
|
||||
mov bx,42
|
||||
call read_string
|
||||
mov edx,[r_pos]
|
||||
mov [f_len],edx
|
||||
;
|
||||
cmp ah,10
|
||||
je still
|
||||
jmp still1
|
||||
.no_file:
|
||||
|
||||
jmp still
|
||||
;E:.
|
||||
|
||||
read_string:
|
||||
;B+ Read string
|
||||
mov [c_place],eax
|
||||
mov [r_pos],0
|
||||
mov [rel_x],60
|
||||
mov [rel_y],bx
|
||||
|
||||
mov ebx,60
|
||||
shl ebx,16
|
||||
mov bx,6*26+1
|
||||
movzx ecx,[rel_y]
|
||||
shl ecx,16
|
||||
mov cx,10
|
||||
mov edx,0x000000
|
||||
mov eax,13
|
||||
int 0x40
|
||||
|
||||
add ecx,11 shl 16
|
||||
mov cx,2
|
||||
mov edx,0x999999
|
||||
int 0x40
|
||||
|
||||
.next:
|
||||
mov ebx,[rel_x]
|
||||
shl ebx,16
|
||||
mov bx,7
|
||||
movzx ecx,[rel_y]
|
||||
shl ecx,16
|
||||
mov cx,10
|
||||
mov edx,0x000000
|
||||
mov eax,13
|
||||
int 0x40
|
||||
|
||||
mov ebx,[c_place]
|
||||
mov byte [ebx],0
|
||||
|
||||
mov eax,10
|
||||
int 0x40
|
||||
cmp eax,2
|
||||
je .key
|
||||
jmp .to_ret
|
||||
.key:
|
||||
|
||||
mov eax,2
|
||||
int 0x40
|
||||
cmp ah,13
|
||||
jne .no_enter
|
||||
jmp .to_ret
|
||||
.no_enter:
|
||||
|
||||
cmp ah,8
|
||||
jne .no_back
|
||||
cmp [r_pos],0
|
||||
je .next
|
||||
dec [r_pos]
|
||||
dec [c_place]
|
||||
sub [rel_x],6
|
||||
jmp .next
|
||||
.no_back:
|
||||
|
||||
cmp [r_pos],25
|
||||
je .next
|
||||
|
||||
cmp ah,'a'
|
||||
jb .no_sm_l
|
||||
cmp ah,'z'
|
||||
ja .no_sm_l
|
||||
add ah,'A'-'a'
|
||||
.no_sm_l:
|
||||
|
||||
mov byte [ebx],ah
|
||||
mov [char],ah
|
||||
inc [c_place]
|
||||
inc [r_pos]
|
||||
|
||||
mov ebx,[rel_x]
|
||||
inc ebx
|
||||
shl ebx,16
|
||||
mov bx,[rel_y]
|
||||
inc bx
|
||||
mov ecx,0x00ffff
|
||||
mov edx,char
|
||||
mov esi,1
|
||||
mov eax,4
|
||||
int 0x40
|
||||
|
||||
add [rel_x],6
|
||||
jmp .next
|
||||
|
||||
.to_ret:
|
||||
push eax
|
||||
mov ebx,60
|
||||
shl ebx,16
|
||||
mov bx,6*26+1
|
||||
movzx ecx,[rel_y]
|
||||
add ecx,11
|
||||
shl ecx,16
|
||||
mov cx,2
|
||||
mov edx,0x000000
|
||||
mov eax,13
|
||||
int 0x40
|
||||
pop eax
|
||||
ret
|
||||
|
||||
rel_x dd 60
|
||||
rel_y dw 0x0
|
||||
c_place dd 0x0
|
||||
r_pos dd 0x0
|
||||
char db '?'
|
||||
;E:.
|
||||
|
||||
draw_window:
|
||||
;B+ Draw window
|
||||
mov eax,12
|
||||
mov ebx,1
|
||||
int 0x40
|
||||
|
||||
mov ebx,100*65536+300
|
||||
mov ecx,100*65536+320
|
||||
mov edx,0x035555DD
|
||||
mov esi,0x805080d0
|
||||
mov edi,0x005080d0
|
||||
mov eax,0
|
||||
int 0x40
|
||||
|
||||
mov ebx,8*65536+8
|
||||
mov ecx,0x10ddeeff
|
||||
mov edx,caption
|
||||
mov esi,caption_end-caption
|
||||
mov eax,4
|
||||
int 0x40
|
||||
|
||||
;mov ebx,(300-19)*65536+12
|
||||
;mov ecx,5*65536+12
|
||||
;mov edx,1
|
||||
;mov esi,0x6688dd
|
||||
;mov eax,8
|
||||
;int 0x40
|
||||
|
||||
;B+ Hot buttons
|
||||
mov ebx,220 shl 16 + 70
|
||||
mov ecx,25 shl 16 + 29
|
||||
mov edx,2 ; compile
|
||||
mov esi,0x6688dd
|
||||
mov eax,8
|
||||
int 0x40
|
||||
|
||||
mov ebx,10 shl 16 + 47
|
||||
mov ecx,26 shl 16 + 12
|
||||
mov edx,3 ; path
|
||||
mov esi,0x6688dd
|
||||
mov eax,8
|
||||
int 0x40
|
||||
|
||||
mov ebx,10 shl 16 + 47
|
||||
mov ecx,41 shl 16 + 12
|
||||
mov edx,4 ; file name
|
||||
mov esi,0x6688dd
|
||||
mov eax,8
|
||||
int 0x40
|
||||
;E:.
|
||||
|
||||
;B+ Text in buttons
|
||||
mov ebx,231 shl 16 + 36
|
||||
mov ecx,0x10ffffff
|
||||
mov edx,txt_compile
|
||||
mov esi,txt_compile_end-txt_compile
|
||||
mov eax,4
|
||||
int 0x40
|
||||
|
||||
mov ebx,14 shl 16 + 28
|
||||
mov ecx,0xffffff
|
||||
mov edx,txt_path
|
||||
mov esi,txt_path_end-txt_path
|
||||
int 0x40
|
||||
|
||||
mov ebx,14 shl 16 + 43
|
||||
mov edx,txt_file
|
||||
mov esi,txt_file_end-txt_file
|
||||
int 0x40
|
||||
;E:.
|
||||
|
||||
;B+ Draw path / file name
|
||||
mov ebx,61 shl 16 + 28
|
||||
mov ecx,0x00ffff
|
||||
mov edx,inp_path
|
||||
mov esi,[p_len]
|
||||
mov eax,4
|
||||
int 0x40
|
||||
|
||||
mov ebx,61 shl 16 + 43
|
||||
mov ecx,0x00ffff
|
||||
mov edx,inp_file
|
||||
mov esi,[f_len]
|
||||
mov eax,4
|
||||
int 0x40
|
||||
;E:.
|
||||
|
||||
mov eax,12
|
||||
mov ebx,2
|
||||
int 0x40
|
||||
|
||||
ret
|
||||
;E:.
|
||||
|
||||
;B+ Data area
|
||||
|
||||
;B+ Interface
|
||||
inp_path: times 100 db '/RD/1/',0
|
||||
p_len dd 6
|
||||
inp_file: times 100 db 'EXAMPLE',0
|
||||
f_len dd 7
|
||||
|
||||
txt_compile db 'Compile'
|
||||
txt_compile_end:
|
||||
txt_path db 'Path ->'
|
||||
txt_path_end:
|
||||
txt_file db 'File ->'
|
||||
txt_file_end:
|
||||
;E:.
|
||||
|
||||
;B+ Main arguments
|
||||
args dd arg_str0,inp_file,arg_str2,arg_str3,arg_str4
|
||||
|
||||
arg_str0 db 'CC',0
|
||||
arg_str1 db 'prog',0
|
||||
arg_str2 db '-m',0
|
||||
arg_str3 db '-a',0
|
||||
arg_str4 db '-p',0
|
||||
;E:.
|
||||
|
||||
;B+ System parameters
|
||||
exit_esp dd 0x0
|
||||
;E:.
|
||||
|
||||
caption db 'Small C compiler for KolibriOS v 0.5.3'
|
||||
caption_end:
|
||||
|
||||
times 8-($ mod 8) db 0
|
||||
;E:.
|
||||
|
||||
I_END:
|
33
programs/develop/scc/STDIO.H
Normal file
33
programs/develop/scc/STDIO.H
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
** STDIO.H -- Standard Small C Definitions.
|
||||
*/
|
||||
|
||||
extern char _iob[];
|
||||
|
||||
#define exit OS_exit
|
||||
#define fopen OS_fopen
|
||||
#define fgetc OS_fgetc
|
||||
#define fputc OS_fputc
|
||||
#define fclose OS_fclose
|
||||
#define calloc OS_calloc // stdlib.h
|
||||
|
||||
#define SIZEOF_FILE 32 // sizeof (FILE)
|
||||
|
||||
#define stdin (&_iob[0])
|
||||
#define stdout (&_iob[1*SIZEOF_FILE])
|
||||
#define stderr (&_iob[2*SIZEOF_FILE])
|
||||
|
||||
#define stdaux 3 /* file descriptor for standard auxiliary port */
|
||||
#define stdprn 4 /* file descriptor for standard printer */
|
||||
#define FILE char /* supports "FILE *fp;" declarations */
|
||||
#define ERR (-2) /* return value for errors */
|
||||
#define EOF (-1) /* return value for end-of-file */
|
||||
#define YES 1 /* true */
|
||||
#define NO 0 /* false */
|
||||
#define NULL 0 /* zero */
|
||||
#define CR 13 /* ASCII carriage return */
|
||||
#define LF 10 /* ASCII line feed */
|
||||
#define BELL 7 /* ASCII bell */
|
||||
#define SPACE ' ' /* ASCII space */
|
||||
#define NEWLINE LF /* Small C newline character */
|
||||
|
320
programs/develop/scc/cc.h
Normal file
320
programs/develop/scc/cc.h
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
** CC.H -- Symbol Definitions for Small-C compiler.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define YES 1 /* true */
|
||||
#define NO 0 /* false */
|
||||
#define CR 13 /* ASCII carriage return */
|
||||
#define LF 10 /* ASCII line feed */
|
||||
#define BELL 7 /* ASCII bell */
|
||||
#define SPACE ' ' /* ASCII space */
|
||||
#define NEWLINE LF /* Small C newline character */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** size of 'int'
|
||||
*/
|
||||
|
||||
#define INT32 /* if #defined int = 32 bits, else 16 */
|
||||
|
||||
/*
|
||||
** ALIGNMENT
|
||||
*/
|
||||
|
||||
#define ALIGN 4
|
||||
|
||||
|
||||
/*
|
||||
** machine dependent parameters
|
||||
*/
|
||||
#define BPD 4 /* bytes per dword */
|
||||
#define LBPD 2 /* log2(BPD) */
|
||||
#define BPW 2 /* bytes per word */
|
||||
#define LBPW 1 /* log2(BPW) */
|
||||
#define SBPC 1 /* stack bytes per character */
|
||||
#define ERRCODE 7 /* op sys return code */
|
||||
#define INTSIZE 4
|
||||
|
||||
/*
|
||||
** symbol table format
|
||||
*/
|
||||
#define IDENT 0
|
||||
#define TYPE 1
|
||||
#define CLASS 2
|
||||
#define SIZE 3
|
||||
#define OFFSET 5+2
|
||||
#define NAME (7+4)
|
||||
|
||||
#define SYMAVG (12+4)
|
||||
#define SYMMAX (16+4)
|
||||
|
||||
/*
|
||||
** symbol table parameters
|
||||
*/
|
||||
#define NUMLOCS 25
|
||||
#define STARTLOC symtab
|
||||
#define ENDLOC (symtab+NUMLOCS*SYMAVG)
|
||||
#define NUMGLBS 200
|
||||
#define STARTGLB ENDLOC
|
||||
#define ENDGLB (ENDLOC+(NUMGLBS-1)*SYMMAX)
|
||||
#define SYMTBSZ /*3050*/ (NUMLOCS*SYMAVG + NUMGLBS*SYMMAX)
|
||||
|
||||
/*
|
||||
** system wide name size (for symbols)
|
||||
*/
|
||||
#define NAMESIZE 9
|
||||
#define NAMEMAX 8
|
||||
|
||||
/*
|
||||
** values for "IDENT"
|
||||
*/
|
||||
#define LABEL 0
|
||||
#define VARIABLE 1
|
||||
#define ARRAY 2
|
||||
#define POINTER 3
|
||||
#define FUNCTION 4
|
||||
|
||||
#define PTRSIZE INTSIZE /* Size of pointer (must match an int!) */
|
||||
|
||||
|
||||
/*
|
||||
** values for "TYPE"
|
||||
** high order 14 bits give length of object
|
||||
** low order 2 bits make type unique within length
|
||||
*/
|
||||
/* LABEL 0 */
|
||||
#define CHR ( 1 << 2)
|
||||
#define SHORT (BPW << 2)
|
||||
#define INT (INTSIZE << 2)
|
||||
#define UCHR (( 1 << 2) + 1)
|
||||
#define USHORT ((BPW << 2) + 1)
|
||||
#define UINT ((INTSIZE << 2) + 1)
|
||||
#define UNSIGNED 1
|
||||
|
||||
/*
|
||||
** values for "CLASS"
|
||||
*/
|
||||
/* LABEL 0 */
|
||||
#define AUTOMATIC 1
|
||||
#define STATIC 2
|
||||
#define EXTERNAL 3
|
||||
#define AUTOEXT 4
|
||||
|
||||
/*
|
||||
** segment types
|
||||
*/
|
||||
#define DATASEG 1
|
||||
#define CODESEG 2
|
||||
|
||||
/*
|
||||
** "switch" table
|
||||
*/
|
||||
#define SWSIZ (2*BPW)
|
||||
#define SWTABSZ (90*SWSIZ)
|
||||
|
||||
/*
|
||||
** "while" queue
|
||||
*/
|
||||
#define WQTABSZ 30
|
||||
#define WQSIZ 3
|
||||
#define WQMAX (wq+WQTABSZ-WQSIZ)
|
||||
|
||||
/*
|
||||
** field offsets in "while" queue
|
||||
*/
|
||||
#define WQSP 0
|
||||
#define WQLOOP 1
|
||||
#define WQEXIT 2
|
||||
|
||||
/*
|
||||
** literal pool
|
||||
*/
|
||||
#define LITABSZ 3000
|
||||
#define LITMAX (LITABSZ-1)
|
||||
|
||||
/*
|
||||
** input line
|
||||
*/
|
||||
#define LINEMAX 127
|
||||
#define LINESIZE 128
|
||||
|
||||
/*
|
||||
** entries in staging buffer
|
||||
*/
|
||||
#define STAGESIZE 200
|
||||
|
||||
/*
|
||||
** macro (#define) pool
|
||||
*/
|
||||
#define MACNBR 300
|
||||
#define MACNSIZE (MACNBR*(NAMESIZE+2))
|
||||
#define MACNEND (macn+MACNSIZE)
|
||||
#define MACQSIZE (MACNBR*7)
|
||||
#define MACMAX (MACQSIZE-1)
|
||||
|
||||
/*
|
||||
** statement types
|
||||
*/
|
||||
#define STIF 1
|
||||
#define STWHILE 2
|
||||
#define STRETURN 3
|
||||
#define STBREAK 4
|
||||
#define STCONT 5
|
||||
#define STASM 6
|
||||
#define STEXPR 7
|
||||
#define STDO 8
|
||||
#define STFOR 9
|
||||
#define STSWITCH 10
|
||||
#define STCASE 11
|
||||
#define STDEF 12
|
||||
#define STGOTO 13
|
||||
#define STLABEL 14
|
||||
|
||||
/*
|
||||
** p-code symbols
|
||||
**
|
||||
** legend:
|
||||
** 1 = primary register (pr in comments)
|
||||
** 2 = secondary register (sr in comments)
|
||||
** b = byte
|
||||
** f = jump on false condition
|
||||
** l = current literal pool label number
|
||||
** m = memory reference by label
|
||||
** n = numeric constant
|
||||
** p = indirect reference thru pointer in sr
|
||||
** r = repeated r times
|
||||
** s = stack frame reference
|
||||
** u = unsigned
|
||||
** w = word
|
||||
** _ (tail) = another p-code completes this one
|
||||
*/
|
||||
|
||||
/* compiler-generated */
|
||||
#define ADD12 1 /* add sr to pr */
|
||||
#define ADDSP 2 /* add to stack pointer */
|
||||
#define AND12 3 /* AND sr to pr */
|
||||
#define ANEG1 4 /* arith negate pr */
|
||||
#define ARGCNTn 5 /* pass arg count to function */
|
||||
#define ASL12 6 /* arith shift left sr by pr into pr */
|
||||
#define ASR12 7 /* arith shift right sr by pr into pr */
|
||||
#define CALL1 8 /* call function thru pr */
|
||||
#define CALLm 9 /* call function directly */
|
||||
#define BYTE_ 10 /* define bytes (part 1) */
|
||||
#define BYTEn 11 /* define byte of value n */
|
||||
#define BYTEr0 12 /* define r bytes of value 0 */
|
||||
#define COM1 13 /* ones complement pr */
|
||||
#define DBL1 14 /* double pr */
|
||||
#define DBL2 15 /* double sr */
|
||||
#define DIV12 16 /* div pr by sr */
|
||||
#define DIV12u 17 /* div pr by sr unsigned */
|
||||
|
||||
#define DWORD_ 111 /* define dword (part 1) */
|
||||
#define DWORDn 112 /* define dword of value n */
|
||||
#define DWORDr0 113 /* define r dwords of value 0 */
|
||||
|
||||
#define ENTER 18 /* set stack frame on function entry */
|
||||
#define EQ10f 19 /* jump if (pr == 0) is false */
|
||||
#define EQ12 20 /* set pr TRUE if (sr == pr) */
|
||||
#define GE10f 21 /* jump if (pr >= 0) is false */
|
||||
#define GE12 22 /* set pr TRUE if (sr >= pr) */
|
||||
#define GE12u 23 /* set pr TRUE if (sr >= pr) unsigned */
|
||||
#define POINT1l 24 /* point pr to function's literal pool */
|
||||
#define POINT1m 25 /* point pr to mem item thru label */
|
||||
#define GETb1m 26 /* get byte into pr from mem thru label */
|
||||
#define GETb1mu 27 /* get unsigned byte into pr from mem thru label */
|
||||
#define GETb1p 28 /* get byte into pr from mem thru sr ptr */
|
||||
#define GETb1pu 29 /* get unsigned byte into pr from mem thru sr ptr */
|
||||
|
||||
#define GETd1m 107 /* get dword into pr from mem thru label */
|
||||
#define GETd1n 108 /* get dword of value n into pr */
|
||||
#define GETd1p 109 /* get dword into pr from mem thru sr ptr */
|
||||
#define GETd2n 110 /* get word of value n into sr */
|
||||
|
||||
#define GETw1m 30 /* get word into pr from mem thru label */
|
||||
#define GETw1n 31 /* get word of value n into pr */
|
||||
#define GETw1p 32 /* get word into pr from mem thru sr ptr */
|
||||
#define GETw2n 33 /* get word of value n into sr */
|
||||
#define GT10f 34 /* jump if (pr > 0) is false */
|
||||
#define GT12 35 /* set pr TRUE if (sr > pr) */
|
||||
#define GT12u 36 /* set pr TRUE if (sr > pr) unsigned */
|
||||
#define WORD_ 37 /* define word (part 1) */
|
||||
#define WORDn 38 /* define word of value n */
|
||||
#define WORDr0 39 /* define r words of value 0 */
|
||||
#define JMPm 40 /* jump to label */
|
||||
#define LABm 41 /* define label m */
|
||||
#define LE10f 42 /* jump if (pr <= 0) is false */
|
||||
#define LE12 43 /* set pr TRUE if (sr <= pr) */
|
||||
#define LE12u 44 /* set pr TRUE if (sr <= pr) unsigned */
|
||||
#define LNEG1 45 /* logical negate pr */
|
||||
#define LT10f 46 /* jump if (pr < 0) is false */
|
||||
#define LT12 47 /* set pr TRUE if (sr < pr) */
|
||||
#define LT12u 48 /* set pr TRUE if (sr < pr) unsigned */
|
||||
#define MOD12 49 /* modulo pr by sr */
|
||||
#define MOD12u 50 /* modulo pr by sr unsigned */
|
||||
#define MOVE21 51 /* move pr to sr */
|
||||
#define MUL12 52 /* multiply pr by sr */
|
||||
#define MUL12u 53 /* multiply pr by sr unsigned */
|
||||
#define NE10f 54 /* jump if (pr != 0) is false */
|
||||
#define NE12 55 /* set pr TRUE if (sr != pr) */
|
||||
#define NEARm 56 /* define near pointer thru label */
|
||||
#define OR12 57 /* OR sr onto pr */
|
||||
#define POINT1s 58 /* point pr to stack item */
|
||||
#define POP2 59 /* pop stack into sr */
|
||||
#define PUSH1 60 /* push pr onto stack */
|
||||
#define PUTbm1 61 /* put pr byte in mem thru label */
|
||||
#define PUTbp1 62 /* put pr byte in mem thru sr ptr */
|
||||
|
||||
#define PUTdm1 114 /* put pr dword in mem thru label */
|
||||
#define PUTdp1 115 /* put pr dword in mem thru sr ptr */
|
||||
|
||||
#define PUTwm1 63 /* put pr word in mem thru label */
|
||||
#define PUTwp1 64 /* put pr word in mem thru sr ptr */
|
||||
#define rDEC1 65 /* dec pr (may repeat) */
|
||||
#define REFm 66 /* finish instruction with label */
|
||||
#define RETURN 67 /* restore stack and return */
|
||||
#define rINC1 68 /* inc pr (may repeat) */
|
||||
#define SUB12 69 /* sub sr from pr */
|
||||
#define SWAP12 70 /* swap pr and sr */
|
||||
#define SWAP1s 71 /* swap pr and top of stack */
|
||||
#define SWITCH 72 /* find switch case */
|
||||
#define XOR12 73 /* XOR pr with sr */
|
||||
|
||||
/* optimizer-generated */
|
||||
#define ADD1n 74 /* add n to pr */
|
||||
#define ADD21 75 /* add pr to sr */
|
||||
#define ADD2n 76 /* add immediate to sr */
|
||||
#define ADDbpn 77 /* add n to mem byte thru sr ptr */
|
||||
#define ADDwpn 78 /* add n to mem word thru sr ptr */
|
||||
#define ADDm_ 79 /* add n to mem byte/word thru label (part 1) */
|
||||
#define COMMAn 80 /* finish instruction with ,n */
|
||||
#define DECbp 81 /* dec mem byte thru sr ptr */
|
||||
#define DECwp 82 /* dec mem word thru sr ptr */
|
||||
#define POINT2m 83 /* point sr to mem thru label */
|
||||
#define POINT2m_ 84 /* point sr to mem thru label (part 1) */
|
||||
#define GETb1s 85 /* get byte into pr from stack */
|
||||
#define GETb1su 86 /* get unsigned byte into pr from stack */
|
||||
#define GETw1m_ 87 /* get word into pr from mem thru label (part 1) */
|
||||
#define GETw1s 88 /* get word into pr from stack */
|
||||
#define GETw2m 89 /* get word into sr from mem (label) */
|
||||
#define GETw2p 90 /* get word into sr thru sr ptr */
|
||||
#define GETw2s 91 /* get word into sr from stack */
|
||||
#define INCbp 92 /* inc byte in mem thru sr ptr */
|
||||
#define INCwp 93 /* inc word in mem thru sr ptr */
|
||||
#define PLUSn 94 /* finish instruction with +n */
|
||||
#define POINT2s 95 /* point sr to stack */
|
||||
#define PUSH2 96 /* push sr */
|
||||
#define PUSHm 97 /* push word from mem thru label */
|
||||
#define PUSHp 98 /* push word from mem thru sr ptr */
|
||||
#define PUSHs 99 /* push word from stack */
|
||||
#define PUT_m_ 100 /* put byte/word into mem thru label (part 1) */
|
||||
#define rDEC2 101 /* dec sr (may repeat) */
|
||||
#define rINC2 102 /* inc sr (may repeat) */
|
||||
#define SUB_m_ 103 /* sub from mem byte/word thru label (part 1) */
|
||||
#define SUB1n 104 /* sub n from pr */
|
||||
#define SUBbpn 105 /* sub n from mem byte thru sr ptr */
|
||||
#define SUBwpn 106 /* sub n from mem word thru sr ptr */
|
||||
|
||||
#define PCODES 116 /* size of code[] (it's a [+ 1]) */
|
||||
|
911
programs/develop/scc/cc1.c
Normal file
911
programs/develop/scc/cc1.c
Normal file
@ -0,0 +1,911 @@
|
||||
/*
|
||||
** Small-C Compiler -- Part 1 -- Top End.
|
||||
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
|
||||
** Copyright 1998 H T Walheim
|
||||
** All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "notice.h"
|
||||
#include "cc.h"
|
||||
|
||||
/*
|
||||
** miscellaneous storage
|
||||
*/
|
||||
int
|
||||
nogo, /* disable goto statements? */
|
||||
noloc, /* disable block locals? */
|
||||
opindex, /* index to matched operator */
|
||||
opsize, /* size of operator in characters */
|
||||
swactive, /* inside a switch? */
|
||||
swdefault,/* default label #, else 0 */
|
||||
*swnext, /* address of next entry */
|
||||
*swend, /* address of last entry */
|
||||
*stage, /* staging buffer address */
|
||||
*wq, /* while queue */
|
||||
argcs, /* static argc */
|
||||
*argvs, /* static argv */
|
||||
*wqptr, /* ptr to next entry */
|
||||
litptr, /* ptr to next entry */
|
||||
macptr, /* macro buffer index */
|
||||
pptr, /* ptr to parsing buffer */
|
||||
ch, /* current character of input line */
|
||||
nch, /* next character of input line */
|
||||
declared, /* # of local bytes to declare, -1 when declared */
|
||||
iflevel, /* #if... nest level */
|
||||
skiplevel,/* level at which #if... skipping started */
|
||||
nxtlab, /* next avail label # */
|
||||
litlab, /* label # assigned to literal pool */
|
||||
csp, /* compiler relative stk ptr */
|
||||
argstk, /* function arg sp */
|
||||
argtop, /* highest formal argument offset */
|
||||
ncmp, /* # open compound statements */
|
||||
errflag, /* true after 1st error in statement */
|
||||
eof, /* true on final input eof */
|
||||
output, /* fd for output file */
|
||||
files, /* true if file list specified on cmd line */
|
||||
filearg = 0, /* cur file arg index */
|
||||
input = EOF, /* fd for input file */
|
||||
input2 = EOF, /* fd for "#include" file */
|
||||
usexpr = YES, /* true if value of expression is used */
|
||||
ccode = YES, /* true while parsing C code */
|
||||
*snext, /* next addr in stage */
|
||||
*stail, /* last addr of data in stage */
|
||||
*slast, /* last addr in stage */
|
||||
listfp, /* file pointer to list device */
|
||||
lastst, /* last parsed statement type */
|
||||
oldseg; /* current segment (0, DATASEG, CODESEG) */
|
||||
|
||||
char
|
||||
optimize, /* optimize output of staging buffer? */
|
||||
alarm, /* audible alarm on errors? */
|
||||
monitor, /* monitor function headers? */
|
||||
pause, /* pause for operator on errors? */
|
||||
*symtab, /* symbol table */
|
||||
*litq, /* literal pool */
|
||||
*macn, /* macro name buffer */
|
||||
*macq, /* macro string buffer */
|
||||
*pline, /* parsing buffer */
|
||||
*mline, /* macro buffer */
|
||||
*line, /* ptr to pline or mline */
|
||||
*lptr, /* ptr to current character in "line" */
|
||||
*glbptr, /* global symbol table */
|
||||
*locptr, /* next local symbol table entry */
|
||||
quote[2] = {'"'}, /* literal string for '"' */
|
||||
*cptr, /* work ptrs to any char buffer */
|
||||
*cptr2,
|
||||
*cptr3,
|
||||
msname[NAMESIZE], /* macro symbol name */
|
||||
ssname[NAMESIZE]; /* static symbol name */
|
||||
|
||||
int op[16] = { /* p-codes of signed binary operators */
|
||||
OR12, /* level5 */
|
||||
XOR12, /* level6 */
|
||||
AND12, /* level7 */
|
||||
EQ12, NE12, /* level8 */
|
||||
LE12, GE12, LT12, GT12, /* level9 */
|
||||
ASR12, ASL12, /* level10 */
|
||||
ADD12, SUB12, /* level11 */
|
||||
MUL12, DIV12, MOD12 /* level12 */
|
||||
};
|
||||
|
||||
int op2[16] = { /* p-codes of unsigned binary operators */
|
||||
OR12, /* level5 */
|
||||
XOR12, /* level6 */
|
||||
AND12, /* level7 */
|
||||
EQ12, NE12, /* level8 */
|
||||
LE12u, GE12u, LT12u, GT12u, /* level9 */
|
||||
ASR12, ASL12, /* level10 */
|
||||
ADD12, SUB12, /* level11 */
|
||||
MUL12u, DIV12u, MOD12u /* level12 */
|
||||
};
|
||||
|
||||
/*
|
||||
** execution begins here
|
||||
*/
|
||||
main(argc, argv) int argc, *argv; {
|
||||
fputs(VERSION, stdout);
|
||||
fputs(CRIGHT1, stdout);
|
||||
fputs(CRIGHT2, stdout);
|
||||
argcs = argc;
|
||||
argvs = argv;
|
||||
swnext = calloc(SWTABSZ, 1);
|
||||
swend = swnext+(SWTABSZ-SWSIZ);
|
||||
stage = calloc(STAGESIZE, 2*INTSIZE);
|
||||
wqptr =
|
||||
wq = calloc(WQTABSZ, INTSIZE);
|
||||
litq = calloc(LITABSZ, 1);
|
||||
macn = calloc(MACNSIZE, 1);
|
||||
macq = calloc(MACQSIZE, 1);
|
||||
pline = calloc(LINESIZE, 1);
|
||||
mline = calloc(LINESIZE, 1);
|
||||
slast = stage+(STAGESIZE*2*INTSIZE);
|
||||
symtab = calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
|
||||
locptr = STARTLOC;
|
||||
glbptr = STARTGLB;
|
||||
|
||||
ask(); /* get user options */
|
||||
openfile(); /* and initial input file */
|
||||
preprocess(); /* fetch first line */
|
||||
header(); /* intro code */
|
||||
setcodes(); /* initialize code pointer array */
|
||||
parse(); /* process ALL input */
|
||||
trailer(); /* follow-up code */
|
||||
fclose(output); /* explicitly close output */
|
||||
}
|
||||
|
||||
/******************** high level parsing *******************/
|
||||
|
||||
/*
|
||||
** process all input text
|
||||
**
|
||||
** At this level, only static declarations,
|
||||
** defines, includes and function
|
||||
** definitions are legal...
|
||||
*/
|
||||
parse() {
|
||||
while (eof == 0) {
|
||||
if (amatch("extern", 6)) dodeclare(EXTERNAL);
|
||||
else if(dodeclare(STATIC)) ;
|
||||
else if( match("#asm")) doasm();
|
||||
else if( match("#include")) doinclude();
|
||||
else if( match("#define")) dodefine();
|
||||
else dofunction();
|
||||
blanks(); /* force eof if pending */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** test for global declarations
|
||||
*/
|
||||
dodeclare(class) int class; {
|
||||
if (amatch("char", 4)) declglb(CHR, class);
|
||||
else if(amatch("unsigned", 8)) {
|
||||
if (amatch("char", 4)) declglb(UCHR, class);
|
||||
else {amatch("int", 3); declglb(UINT, class);}
|
||||
}
|
||||
else if(amatch("int", 3)
|
||||
|| class == EXTERNAL) declglb(INT, class);
|
||||
else return 0;
|
||||
ns();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** declare a static variable
|
||||
*/
|
||||
declglb(type, class)
|
||||
int type, class;
|
||||
{
|
||||
int id, dim;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(endst())
|
||||
return; /* do line */
|
||||
if(match("*"))
|
||||
{
|
||||
id = POINTER; dim = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = VARIABLE; dim = 1;
|
||||
}
|
||||
if(symname(ssname) == 0)
|
||||
illname();
|
||||
if(findglb(ssname))
|
||||
multidef(ssname);
|
||||
if(id == VARIABLE)
|
||||
{
|
||||
if (match("("))
|
||||
{
|
||||
id = FUNCTION; need(")");
|
||||
}
|
||||
else if(match("["))
|
||||
{
|
||||
id = ARRAY; dim = needsub();
|
||||
}
|
||||
}
|
||||
if (class == EXTERNAL)
|
||||
external(ssname, type >> 2, id);
|
||||
else if (id != FUNCTION)
|
||||
initials(type >> 2, id, dim);
|
||||
if(id == POINTER)
|
||||
addsym(ssname, id, type, PTRSIZE, 0, &glbptr, class);
|
||||
else
|
||||
addsym(ssname, id, type, dim * (type >> 2), 0, &glbptr, class);
|
||||
if(match(",") == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** initialize global objects
|
||||
*/
|
||||
initials(size, ident, dim) int size, ident, dim; {
|
||||
int savedim;
|
||||
litptr = 0;
|
||||
if(dim == 0) dim = -1; /* *... or ...[] */
|
||||
savedim = dim;
|
||||
/* public(ident); */
|
||||
if(match("=")) {
|
||||
if(match("{")) {
|
||||
while(dim) {
|
||||
init(size, ident, &dim);
|
||||
if(match(",") == 0) break;
|
||||
}
|
||||
need("}");
|
||||
}
|
||||
else init(size, ident, &dim);
|
||||
}
|
||||
if(savedim == -1 && dim == -1) {
|
||||
if(ident == ARRAY) error("need array size");
|
||||
stowlit(0, size = PTRSIZE);
|
||||
}
|
||||
|
||||
/* FASM */
|
||||
public(ident);
|
||||
if(litptr>0) dumplits(size);
|
||||
else if(dim>0)
|
||||
{/*In FASM: "<variable>: TIMES <number> D<type> 0" */
|
||||
fputc(':',output);
|
||||
}
|
||||
dumpzero(size, dim); /* only if dim > 0 */
|
||||
/* FASM */
|
||||
}
|
||||
|
||||
/*
|
||||
** evaluate one initializer
|
||||
*/
|
||||
init(size, ident, dim) int size, ident, *dim; {
|
||||
int value;
|
||||
if(string(&value)) {
|
||||
if(ident == VARIABLE || size != 1)
|
||||
error("must assign to char pointer or char array");
|
||||
*dim -= (litptr - value);
|
||||
if(ident == POINTER) point();
|
||||
}
|
||||
else if(constexpr(&value)) {
|
||||
if(ident == POINTER) error("cannot assign to pointer");
|
||||
stowlit(value, size);
|
||||
*dim -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** get required array size
|
||||
*/
|
||||
needsub() {
|
||||
int val;
|
||||
if(match("]")) return 0; /* null size */
|
||||
if(constexpr(&val) == 0) val = 1;
|
||||
if(val < 0) {
|
||||
error("negative size illegal");
|
||||
val = -val;
|
||||
}
|
||||
need("]"); /* force single dimension */
|
||||
return val; /* and return size */
|
||||
}
|
||||
|
||||
/*
|
||||
** open an include file
|
||||
*/
|
||||
doinclude() {
|
||||
int i; char str[30];
|
||||
blanks(); /* skip over to name */
|
||||
if(*lptr == '"' || *lptr == '<') ++lptr;
|
||||
i = 0;
|
||||
while(lptr[i]
|
||||
&& lptr[i] != '"'
|
||||
&& lptr[i] != '>'
|
||||
&& lptr[i] != '\n') {
|
||||
str[i] = lptr[i];
|
||||
++i;
|
||||
}
|
||||
str[i] = NULL;
|
||||
if((input2 = fopen(str,"r")) == NULL) {
|
||||
input2 = EOF;
|
||||
error("open failure on include file");
|
||||
}
|
||||
kill(); /* make next read come from new file (if open) */
|
||||
}
|
||||
|
||||
/*
|
||||
** define a macro symbol
|
||||
*/
|
||||
dodefine() {
|
||||
int k;
|
||||
if(symname(msname) == 0) {
|
||||
illname();
|
||||
kill();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
puts (msname);
|
||||
puts (" is #defined\n");
|
||||
*/
|
||||
k = 0;
|
||||
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0) {
|
||||
if(cptr2 = cptr)
|
||||
while(*cptr2++ = msname[k++]) ;
|
||||
else {
|
||||
error("macro name table full");
|
||||
return;
|
||||
}
|
||||
}
|
||||
putint(macptr, cptr+NAMESIZE, 2 /*INTSIZE*/);
|
||||
while(white()) gch();
|
||||
while(putmac(gch()));
|
||||
if(macptr >= MACMAX) {
|
||||
error("macro string queue full");
|
||||
exit(ERRCODE);
|
||||
}
|
||||
}
|
||||
|
||||
putmac(c) char c; {
|
||||
macq[macptr] = c;
|
||||
if(macptr < MACMAX) ++macptr;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
** begin a function
|
||||
**
|
||||
** called from "parse" and tries to make a function
|
||||
** out of the following text
|
||||
*/
|
||||
dofunction() {
|
||||
char *ptr;
|
||||
nogo = /* enable goto statements */
|
||||
noloc = /* enable block-local declarations */
|
||||
lastst = /* no statement yet */
|
||||
litptr = 0; /* clear lit pool */
|
||||
litlab = getlabel(); /* label next lit pool */
|
||||
locptr = STARTLOC; /* clear local variables */
|
||||
if(match("void")) blanks(); /* skip "void" & locate header */
|
||||
if(monitor) lout(line, stderr);
|
||||
if(symname(ssname) == 0) {
|
||||
error("illegal function or declaration");
|
||||
errflag = 0;
|
||||
kill(); /* invalidate line */
|
||||
return;
|
||||
}
|
||||
if(ptr = findglb(ssname)) { /* already in symbol table? */
|
||||
if(ptr[CLASS] == AUTOEXT)
|
||||
ptr[CLASS] = STATIC;
|
||||
else multidef(ssname);
|
||||
}
|
||||
else addsym(ssname, FUNCTION, INT, 0, 0, &glbptr, STATIC);
|
||||
public(FUNCTION);
|
||||
argstk = 0; /* init arg count */
|
||||
if(match("(") == 0) error("no open paren");
|
||||
while(match(")") == 0) { /* then count args */
|
||||
if(symname(ssname)) {
|
||||
if(findloc(ssname)) multidef(ssname);
|
||||
else {
|
||||
addsym(ssname, 0, 0, 0, argstk, &locptr, AUTOMATIC);
|
||||
argstk += INTSIZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error("illegal argument name");
|
||||
skip();
|
||||
}
|
||||
blanks();
|
||||
if(streq(lptr,")") == 0 && match(",") == 0)
|
||||
error("no comma");
|
||||
if(endst()) break;
|
||||
}
|
||||
csp = 0; /* preset stack ptr */
|
||||
argtop = argstk+INTSIZE; /* account for the pushed BP */
|
||||
while(argstk) {
|
||||
if (amatch("char", 4)) {doargs(CHR); ns();}
|
||||
else if(amatch("int", 3)) {doargs(INT); ns();}
|
||||
else if(amatch("unsigned", 8)) {
|
||||
if (amatch("char", 4)) {doargs(UCHR); ns();}
|
||||
else {amatch("int", 3); doargs(UINT); ns();}
|
||||
}
|
||||
else {error("wrong number of arguments"); break;}
|
||||
}
|
||||
gen(ENTER, 0);
|
||||
statement();
|
||||
if(lastst != STRETURN && lastst != STGOTO)
|
||||
gen(RETURN, 0);
|
||||
if(litptr) {
|
||||
toseg(DATASEG);
|
||||
gen(REFm, litlab);
|
||||
dumplits(1); /* dump literals */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** declare argument types
|
||||
*/
|
||||
doargs(type) int type; {
|
||||
int id, sz;
|
||||
char c, *ptr;
|
||||
while(1) {
|
||||
if(argstk == 0) return; /* no arguments */
|
||||
if(decl(type, POINTER, &id, &sz)) {
|
||||
if(ptr = findloc(ssname)) {
|
||||
ptr[IDENT] = id;
|
||||
ptr[TYPE] = type;
|
||||
putint(sz, ptr+SIZE, INTSIZE);
|
||||
putint(argtop-getint(ptr+OFFSET, INTSIZE), ptr+OFFSET, INTSIZE);
|
||||
}
|
||||
else error("not an argument");
|
||||
}
|
||||
argstk = argstk - INTSIZE; /* cnt down */
|
||||
if(endst()) return;
|
||||
if(match(",") == 0) error("no comma");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** parse next local or argument declaration
|
||||
*/
|
||||
decl(type, aid, id, sz)
|
||||
int type, aid, *id, *sz;
|
||||
{
|
||||
int n, p;
|
||||
int mod;
|
||||
if(match("(")) p = 1;
|
||||
else p = 0;
|
||||
if(match("*")) {*id = POINTER; *sz = PTRSIZE;}
|
||||
else {*id = VARIABLE; *sz = type >> 2;}
|
||||
if((n = symname(ssname)) == 0) illname();
|
||||
if(p && match(")")) ;
|
||||
if(match("("))
|
||||
{
|
||||
if(!p || *id != POINTER)
|
||||
error("try (*...)()");
|
||||
need(")");
|
||||
}
|
||||
else if(*id == VARIABLE && match("["))
|
||||
{
|
||||
*id = aid;
|
||||
if((*sz *= needsub()) == 0)
|
||||
{
|
||||
if(aid == ARRAY) error("need array size");
|
||||
*sz = PTRSIZE; /* size of pointer argument */
|
||||
}
|
||||
}
|
||||
mod = *sz % ALIGN;
|
||||
|
||||
if (mod)
|
||||
{
|
||||
*sz = *sz + (ALIGN-mod);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/******************** start 2nd level parsing *******************/
|
||||
|
||||
/*
|
||||
** statement parser
|
||||
*/
|
||||
statement() {
|
||||
if(ch == 0 && eof) return;
|
||||
else if(amatch("char", 4)) {declloc(CHR); ns();}
|
||||
else if(amatch("int", 3)) {declloc(INT); ns();}
|
||||
else if(amatch("unsigned", 8)) {
|
||||
if (amatch("char", 4)) {declloc(UCHR); ns();}
|
||||
else {amatch("int", 3); declloc(UINT); ns();}
|
||||
}
|
||||
else {
|
||||
if(declared >= 0) {
|
||||
if(ncmp > 1) nogo = declared; /* disable goto */
|
||||
gen(ADDSP, csp - declared);
|
||||
declared = -1;
|
||||
}
|
||||
if(match("{")) compound();
|
||||
else if(amatch("if", 2)) {doif(); lastst = STIF;}
|
||||
else if(amatch("while", 5)) {dowhile(); lastst = STWHILE;}
|
||||
else if(amatch("do", 2)) {dodo(); lastst = STDO;}
|
||||
else if(amatch("for", 3)) {dofor(); lastst = STFOR;}
|
||||
else if(amatch("switch", 6)) {doswitch(); lastst = STSWITCH;}
|
||||
else if(amatch("case", 4)) {docase(); lastst = STCASE;}
|
||||
else if(amatch("default", 7)) {dodefault(); lastst = STDEF;}
|
||||
else if(amatch("goto", 4)) {dogoto(); lastst = STGOTO;}
|
||||
else if(dolabel()) lastst = STLABEL;
|
||||
else if(amatch("return", 6)) {doreturn(); ns(); lastst = STRETURN;}
|
||||
else if(amatch("break", 5)) {dobreak(); ns(); lastst = STBREAK;}
|
||||
else if(amatch("continue", 8)) {docont(); ns(); lastst = STCONT;}
|
||||
else if(match(";")) errflag = 0;
|
||||
else if(match("#asm")) {doasm(); lastst = STASM;}
|
||||
else {doexpr(NO); ns(); lastst = STEXPR;}
|
||||
}
|
||||
return lastst;
|
||||
}
|
||||
|
||||
/*
|
||||
** declare local variables
|
||||
*/
|
||||
declloc(type) int type; {
|
||||
int id, sz;
|
||||
if(swactive) error("not allowed in switch");
|
||||
if(noloc) error("not allowed with goto");
|
||||
if(declared < 0) error("must declare first in block");
|
||||
while(1) {
|
||||
if(endst()) return;
|
||||
decl(type, ARRAY, &id, &sz);
|
||||
declared += sz;
|
||||
addsym(ssname, id, type, sz, csp - declared, &locptr, AUTOMATIC);
|
||||
if(match(",") == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
compound() {
|
||||
int savcsp;
|
||||
char *savloc;
|
||||
savcsp = csp;
|
||||
savloc = locptr;
|
||||
declared = 0; /* may now declare local variables */
|
||||
++ncmp; /* new level open */
|
||||
while (match("}") == 0)
|
||||
if(eof) {
|
||||
error("no final }");
|
||||
break;
|
||||
}
|
||||
else statement(); /* do one */
|
||||
if(--ncmp /* close current level */
|
||||
&& lastst != STRETURN
|
||||
&& lastst != STGOTO)
|
||||
gen(ADDSP, savcsp); /* delete local variable space */
|
||||
cptr = savloc; /* retain labels */
|
||||
while(cptr < locptr) {
|
||||
cptr2 = nextsym(cptr);
|
||||
if(cptr[IDENT] == LABEL) {
|
||||
while(cptr < cptr2) *savloc++ = *cptr++;
|
||||
}
|
||||
else cptr = cptr2;
|
||||
}
|
||||
locptr = savloc; /* delete local symbols */
|
||||
declared = -1; /* may not declare variables */
|
||||
}
|
||||
|
||||
doif() {
|
||||
int flab1, flab2;
|
||||
test(flab1 = getlabel(), YES); /* get expr, and branch false */
|
||||
statement(); /* if true, do a statement */
|
||||
if(amatch("else", 4) == 0) { /* if...else ? */
|
||||
/* simple "if"...print false label */
|
||||
gen(LABm, flab1);
|
||||
return; /* and exit */
|
||||
}
|
||||
flab2 = getlabel();
|
||||
if(lastst != STRETURN && lastst != STGOTO)
|
||||
gen(JMPm, flab2);
|
||||
gen(LABm, flab1); /* print false label */
|
||||
statement(); /* and do "else" clause */
|
||||
gen(LABm, flab2); /* print true label */
|
||||
}
|
||||
|
||||
dowhile() {
|
||||
int wq[4]; /* allocate local queue */
|
||||
addwhile(wq); /* add entry to queue for "break" */
|
||||
gen(LABm, wq[WQLOOP]); /* loop label */
|
||||
test(wq[WQEXIT], YES); /* see if true */
|
||||
statement(); /* if so, do a statement */
|
||||
gen(JMPm, wq[WQLOOP]); /* loop to label */
|
||||
gen(LABm, wq[WQEXIT]); /* exit label */
|
||||
delwhile(); /* delete queue entry */
|
||||
}
|
||||
|
||||
dodo() {
|
||||
int wq[4];
|
||||
addwhile(wq);
|
||||
gen(LABm, wq[WQLOOP]);
|
||||
statement();
|
||||
need("while");
|
||||
test(wq[WQEXIT], YES);
|
||||
gen(JMPm, wq[WQLOOP]);
|
||||
gen(LABm, wq[WQEXIT]);
|
||||
delwhile();
|
||||
ns();
|
||||
}
|
||||
|
||||
dofor() {
|
||||
int wq[4], lab1, lab2;
|
||||
addwhile(wq);
|
||||
lab1 = getlabel();
|
||||
lab2 = getlabel();
|
||||
need("(");
|
||||
if(match(";") == 0) {
|
||||
doexpr(NO); /* expr 1 */
|
||||
ns();
|
||||
}
|
||||
gen(LABm, lab1);
|
||||
if(match(";") == 0) {
|
||||
test(wq[WQEXIT], NO); /* expr 2 */
|
||||
ns();
|
||||
}
|
||||
gen(JMPm, lab2);
|
||||
gen(LABm, wq[WQLOOP]);
|
||||
if(match(")") == 0) {
|
||||
doexpr(NO); /* expr 3 */
|
||||
need(")");
|
||||
}
|
||||
gen(JMPm, lab1);
|
||||
gen(LABm, lab2);
|
||||
statement();
|
||||
gen(JMPm, wq[WQLOOP]);
|
||||
gen(LABm, wq[WQEXIT]);
|
||||
delwhile();
|
||||
}
|
||||
|
||||
doswitch() {
|
||||
int wq[4], endlab, swact, swdef, *swnex, *swptr;
|
||||
swact = swactive;
|
||||
swdef = swdefault;
|
||||
swnex = swptr = swnext;
|
||||
addwhile(wq);
|
||||
*(wqptr + WQLOOP - WQSIZ) = 0;
|
||||
need("(");
|
||||
doexpr(YES); /* evaluate switch expression */
|
||||
need(")");
|
||||
swdefault = 0;
|
||||
swactive = 1;
|
||||
gen(JMPm, endlab = getlabel());
|
||||
statement(); /* cases, etc. */
|
||||
gen(JMPm, wq[WQEXIT]);
|
||||
gen(LABm, endlab);
|
||||
gen(SWITCH, 0); /* match cases */
|
||||
while(swptr < swnext) {
|
||||
gen(NEARm, *swptr++);
|
||||
#ifdef INT32
|
||||
gen(DWORDn, *swptr++); /* case value */
|
||||
#else
|
||||
gen(WORDn, *swptr++); /* case value */
|
||||
#endif
|
||||
}
|
||||
#ifdef INT32
|
||||
gen(DWORDn, 0);
|
||||
#else
|
||||
gen(WORDn, 0);
|
||||
#endif
|
||||
if(swdefault) gen(JMPm, swdefault);
|
||||
gen(LABm, wq[WQEXIT]);
|
||||
delwhile();
|
||||
swnext = swnex;
|
||||
swdefault = swdef;
|
||||
swactive = swact;
|
||||
}
|
||||
|
||||
docase() {
|
||||
if(swactive == 0) error("not in switch");
|
||||
if(swnext > swend) {
|
||||
error("too many cases");
|
||||
return;
|
||||
}
|
||||
gen(LABm, *swnext++ = getlabel());
|
||||
constexpr(swnext++);
|
||||
need(":");
|
||||
}
|
||||
|
||||
dodefault() {
|
||||
if(swactive) {
|
||||
if(swdefault) error("multiple defaults");
|
||||
}
|
||||
else error("not in switch");
|
||||
need(":");
|
||||
gen(LABm, swdefault = getlabel());
|
||||
}
|
||||
|
||||
dogoto() {
|
||||
if(nogo > 0) error("not allowed with block-locals");
|
||||
else noloc = 1;
|
||||
if(symname(ssname)) gen(JMPm, addlabel(NO));
|
||||
else error("bad label");
|
||||
ns();
|
||||
}
|
||||
|
||||
dolabel() {
|
||||
char *savelptr;
|
||||
blanks();
|
||||
savelptr = lptr;
|
||||
if(symname(ssname)) {
|
||||
if(gch() == ':') {
|
||||
gen(LABm, addlabel(YES));
|
||||
return 1;
|
||||
}
|
||||
else bump(savelptr-lptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
addlabel(def) int def; {
|
||||
if(cptr = findloc(ssname)) {
|
||||
if(cptr[IDENT] != LABEL) error("not a label");
|
||||
else if(def) {
|
||||
if(cptr[TYPE]) error("duplicate label");
|
||||
else cptr[TYPE] = YES;
|
||||
}
|
||||
}
|
||||
else cptr = addsym(ssname, LABEL, def, 0, getlabel(), &locptr, LABEL);
|
||||
return (getint(cptr+OFFSET, INTSIZE));
|
||||
}
|
||||
|
||||
doreturn() {
|
||||
int savcsp;
|
||||
if(endst() == 0) doexpr(YES);
|
||||
savcsp = csp;
|
||||
gen(RETURN, 0);
|
||||
csp = savcsp;
|
||||
}
|
||||
|
||||
dobreak() {
|
||||
int *ptr;
|
||||
if((ptr = readwhile(wqptr)) == 0) return;
|
||||
gen(ADDSP, ptr[WQSP]);
|
||||
gen(JMPm, ptr[WQEXIT]);
|
||||
}
|
||||
|
||||
docont() {
|
||||
int *ptr;
|
||||
ptr = wqptr;
|
||||
while (1) {
|
||||
if((ptr = readwhile(ptr)) == 0) return;
|
||||
if(ptr[WQLOOP]) break;
|
||||
}
|
||||
gen(ADDSP, ptr[WQSP]);
|
||||
gen(JMPm, ptr[WQLOOP]);
|
||||
}
|
||||
|
||||
doasm() {
|
||||
ccode = 0; /* mark mode as "asm" */
|
||||
while (1) {
|
||||
inline();
|
||||
if(match("#endasm")) break;
|
||||
if(eof)break;
|
||||
fputs(line, output);
|
||||
}
|
||||
kill();
|
||||
ccode = 1;
|
||||
}
|
||||
|
||||
doexpr(use) int use; {
|
||||
int constant, val;
|
||||
int *before, *start;
|
||||
usexpr = use; /* tell isfree() whether expr value is used */
|
||||
while(1) {
|
||||
setstage(&before, &start);
|
||||
expression(&constant, &val);
|
||||
clearstage(before, start);
|
||||
if(ch != ',') break;
|
||||
bump(1);
|
||||
}
|
||||
usexpr = YES; /* return to normal value */
|
||||
}
|
||||
|
||||
/******************** miscellaneous functions *******************/
|
||||
|
||||
/*
|
||||
** get run options
|
||||
*/
|
||||
ask()
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
i = listfp = nxtlab = 0;
|
||||
output = stdout;
|
||||
#ifdef LATER
|
||||
optimize = YES; // Not working for 32 bit int's yer
|
||||
#else
|
||||
optimize = NO;
|
||||
#endif
|
||||
alarm = monitor = pause = NO;
|
||||
line = mline;
|
||||
while(getarg(++i, line, LINESIZE, argcs, argvs) != EOF)
|
||||
{
|
||||
if(line[0] != '-' && line[0] != '/')
|
||||
continue;
|
||||
if(toupper(line[1]) == 'L' // List
|
||||
&& isdigit(line[2])
|
||||
&& line[3] <= ' ')
|
||||
{
|
||||
listfp = line[2]-'0';
|
||||
continue;
|
||||
}
|
||||
if(toupper(line[1]) == 'N' // No optimize
|
||||
&& toupper(line[2]) == 'O'
|
||||
&& line[3] <= ' ')
|
||||
{
|
||||
optimize = NO;
|
||||
continue;
|
||||
}
|
||||
if(toupper(line[1]) == 'D')
|
||||
{
|
||||
j = 0;
|
||||
ch = line[j+2];
|
||||
lptr = line + j+2;
|
||||
/*
|
||||
while (line[j+2] != ' ')
|
||||
{
|
||||
if (j < (NAMEMAX-1))
|
||||
{
|
||||
msname[j] = line[j+1];
|
||||
++j;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
msname[j] = '\0';
|
||||
*/
|
||||
dodefine ();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(line[2] <= ' ')
|
||||
{
|
||||
if(toupper(line[1]) == 'A') {alarm = YES; continue;}
|
||||
if(toupper(line[1]) == 'M') {monitor = YES; continue;}
|
||||
if(toupper(line[1]) == 'P') {pause = YES; continue;}
|
||||
}
|
||||
fputs("usage: cc [file]... [-m] [-a] [-p] [-l#] [-no] [-d<id>]\n", stderr);
|
||||
fputs(" -m monitor\n", stderr);
|
||||
fputs(" -a alarm\n", stderr);
|
||||
fputs(" -p pause\n", stderr);
|
||||
fputs(" -l# list\n", stderr);
|
||||
fputs(" -no no optimize\n", stderr);
|
||||
fputs(" -d<id> pre-#define id\n", stderr);
|
||||
exit(ERRCODE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** input and output file opens
|
||||
*/
|
||||
openfile() { /* entire function revised */
|
||||
char outfn[15];
|
||||
int i, j, ext;
|
||||
input = EOF;
|
||||
while(getarg(++filearg, pline, LINESIZE, argcs, argvs) != EOF) {
|
||||
if(pline[0] == '-' || pline[0] == '/') continue;
|
||||
ext = NO;
|
||||
i = -1;
|
||||
j = 0;
|
||||
while(pline[++i]) {
|
||||
if(pline[i] == '.') {
|
||||
ext = YES;
|
||||
break;
|
||||
}
|
||||
if(j < 10) outfn[j++] = pline[i];
|
||||
}
|
||||
if(!ext) strcpy(pline + i, ".C");
|
||||
input = mustopen(pline, "r");
|
||||
#ifdef _MSC_VER
|
||||
|
||||
if(!files) {
|
||||
strcpy(outfn + j, ".ASM");
|
||||
output = mustopen(outfn, "w");
|
||||
}
|
||||
|
||||
#else
|
||||
if(!files /* && iscons(stdout)*/) {
|
||||
strcpy(outfn + j, ".ASM");
|
||||
output = mustopen(outfn, "w");
|
||||
}
|
||||
#endif
|
||||
files = YES;
|
||||
kill();
|
||||
return;
|
||||
}
|
||||
if(files++) eof = YES;
|
||||
else input = stdin;
|
||||
kill();
|
||||
}
|
||||
|
||||
/*
|
||||
** open a file with error checking
|
||||
*/
|
||||
mustopen(fn, mode) char *fn, *mode; {
|
||||
int fd;
|
||||
if(fd = fopen(fn, mode)) return fd;
|
||||
fputs("open error on ", stderr);
|
||||
lout(fn, stderr);
|
||||
exit(ERRCODE);
|
||||
}
|
||||
|
557
programs/develop/scc/cc2.c
Normal file
557
programs/develop/scc/cc2.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.
|
||||
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
|
||||
** Copyright 1998 H T Walheim
|
||||
** All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cc.h"
|
||||
|
||||
extern char
|
||||
*symtab, *macn, *macq, *pline, *mline, optimize,
|
||||
alarm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3,
|
||||
*locptr, msname[NAMESIZE], pause, quote[2];
|
||||
|
||||
extern int
|
||||
*wq, ccode, ch, csp, eof, errflag, iflevel,
|
||||
input, input2, listfp, macptr, nch,
|
||||
nxtlab, op[16], opindex, opsize, output, pptr,
|
||||
skiplevel, *wqptr;
|
||||
|
||||
/********************** input functions **********************/
|
||||
|
||||
preprocess() {
|
||||
int k;
|
||||
char c;
|
||||
if(ccode) {
|
||||
line = mline;
|
||||
ifline();
|
||||
if(eof) return;
|
||||
}
|
||||
else {
|
||||
inline();
|
||||
return;
|
||||
}
|
||||
pptr = -1;
|
||||
while(ch != NEWLINE && ch) {
|
||||
if(white()) {
|
||||
keepch(' ');
|
||||
while(white()) gch();
|
||||
}
|
||||
else if(ch == '"') {
|
||||
keepch(ch);
|
||||
gch();
|
||||
while(ch != '"' || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
|
||||
if(ch == NULL) {
|
||||
error("no quote");
|
||||
break;
|
||||
}
|
||||
keepch(gch());
|
||||
}
|
||||
gch();
|
||||
keepch('"');
|
||||
}
|
||||
else if(ch == 39) {
|
||||
keepch(39);
|
||||
gch();
|
||||
while(ch != 39 || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
|
||||
if(ch == NULL) {
|
||||
error("no apostrophe");
|
||||
break;
|
||||
}
|
||||
keepch(gch());
|
||||
}
|
||||
gch();
|
||||
keepch(39);
|
||||
}
|
||||
else if(ch == '/' && nch == '*')
|
||||
{
|
||||
bump(2);
|
||||
while((ch == '*' && nch == '/') == 0)
|
||||
{
|
||||
if(ch)
|
||||
bump(1);
|
||||
else
|
||||
{
|
||||
ifline();
|
||||
if(eof)
|
||||
break;
|
||||
}
|
||||
}
|
||||
bump(2);
|
||||
}
|
||||
else if(ch == '/' && nch == '/')
|
||||
{
|
||||
bump(2);
|
||||
while(ch != NEWLINE)
|
||||
{
|
||||
if(ch)
|
||||
bump(1);
|
||||
else
|
||||
{
|
||||
if(eof)
|
||||
break;
|
||||
}
|
||||
}
|
||||
bump(1);
|
||||
}
|
||||
else if(an(ch)) {
|
||||
k = 0;
|
||||
while(an(ch) && k < NAMEMAX) {
|
||||
msname[k++] = ch;
|
||||
gch();
|
||||
}
|
||||
msname[k] = NULL;
|
||||
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
|
||||
k = getint(cptr+NAMESIZE, 2/*INTSIZE*/);
|
||||
while(c = macq[k++]) keepch(c);
|
||||
while(an(ch)) gch();
|
||||
}
|
||||
else {
|
||||
k = 0;
|
||||
while(c = msname[k++]) keepch(c);
|
||||
}
|
||||
}
|
||||
else keepch(gch());
|
||||
}
|
||||
if(pptr >= LINEMAX) error("line too long");
|
||||
keepch(NULL);
|
||||
line = pline;
|
||||
bump(0);
|
||||
}
|
||||
|
||||
keepch(c) char c; {
|
||||
if(pptr < LINEMAX) pline[++pptr] = c;
|
||||
}
|
||||
|
||||
ifline() {
|
||||
while(1) {
|
||||
inline();
|
||||
if(eof) return;
|
||||
if(match("#ifdef")) {
|
||||
++iflevel;
|
||||
if(skiplevel) continue;
|
||||
symname(msname);
|
||||
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0)
|
||||
skiplevel = iflevel;
|
||||
continue;
|
||||
}
|
||||
if(match("#ifndef")) {
|
||||
++iflevel;
|
||||
if(skiplevel) continue;
|
||||
symname(msname);
|
||||
if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
|
||||
skiplevel = iflevel;
|
||||
continue;
|
||||
}
|
||||
if(match("#else")) {
|
||||
if(iflevel) {
|
||||
if(skiplevel == iflevel) skiplevel = 0;
|
||||
else if(skiplevel == 0) skiplevel = iflevel;
|
||||
}
|
||||
else noiferr();
|
||||
continue;
|
||||
}
|
||||
if(match("#endif")) {
|
||||
if(iflevel) {
|
||||
if(skiplevel == iflevel) skiplevel = 0;
|
||||
--iflevel;
|
||||
}
|
||||
else noiferr();
|
||||
continue;
|
||||
}
|
||||
if(skiplevel) continue;
|
||||
if(ch == 0) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline() { /* numerous revisions */
|
||||
int k, unit;
|
||||
|
||||
if(input == EOF) openfile();
|
||||
if(eof) return;
|
||||
if((unit = input2) == EOF) unit = input;
|
||||
if(fgets(line, LINEMAX, unit) == NULL) {
|
||||
fclose(unit);
|
||||
if(input2 != EOF)
|
||||
input2 = EOF;
|
||||
else input = EOF;
|
||||
*line = NULL;
|
||||
}
|
||||
else if(listfp)
|
||||
{
|
||||
if(listfp == output) fputc(';', output);
|
||||
fputs(line, listfp);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
else
|
||||
{
|
||||
fputc(';', output);
|
||||
fputs(line, output);
|
||||
}
|
||||
#endif
|
||||
bump(0);
|
||||
}
|
||||
|
||||
inbyte() {
|
||||
while(ch == 0) {
|
||||
if(eof) return 0;
|
||||
preprocess();
|
||||
}
|
||||
return gch();
|
||||
}
|
||||
|
||||
/********************* scanning functions ********************/
|
||||
|
||||
/*
|
||||
** test if next input string is legal symbol name
|
||||
*/
|
||||
symname(sname) char *sname; {
|
||||
int k;char c;
|
||||
blanks();
|
||||
if(alpha(ch) == 0) return (*sname = 0);
|
||||
k = 0;
|
||||
while(an(ch)) {
|
||||
sname[k] = gch();
|
||||
if(k < NAMEMAX) ++k;
|
||||
}
|
||||
sname[k] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
need(str) char *str; {
|
||||
if(match(str) == 0) error("missing token");
|
||||
}
|
||||
|
||||
ns() {
|
||||
if(match(";") == 0) error("no semicolon");
|
||||
else errflag = 0;
|
||||
}
|
||||
|
||||
match(lit) char *lit; {
|
||||
int k;
|
||||
blanks();
|
||||
if(k = streq(lptr, lit)) {
|
||||
bump(k);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
streq(str1, str2) char str1[], str2[]; {
|
||||
int k;
|
||||
k = 0;
|
||||
while (str2[k]) {
|
||||
if(str1[k] != str2[k]) return 0;
|
||||
++k;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
amatch(lit, len) char *lit; int len; {
|
||||
int k;
|
||||
blanks();
|
||||
if(k = astreq(lptr, lit, len)) {
|
||||
bump(k);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
astreq(str1, str2, len) char str1[], str2[]; int len; {
|
||||
int k;
|
||||
k = 0;
|
||||
while (k < len) {
|
||||
if(str1[k] != str2[k]) break;
|
||||
/*
|
||||
** must detect end of symbol table names terminated by
|
||||
** symbol length in binary
|
||||
*/
|
||||
if(str2[k] < ' ') break;
|
||||
if(str1[k] < ' ') break;
|
||||
++k;
|
||||
}
|
||||
if(an(str1[k]) || an(str2[k])) return 0;
|
||||
return k;
|
||||
}
|
||||
|
||||
nextop(list) char *list; {
|
||||
char op[4];
|
||||
opindex = 0;
|
||||
blanks();
|
||||
while(1) {
|
||||
opsize = 0;
|
||||
while(*list > ' ') op[opsize++] = *list++;
|
||||
op[opsize] = 0;
|
||||
if(opsize = streq(lptr, op))
|
||||
if(*(lptr+opsize) != '=' &&
|
||||
*(lptr+opsize) != *(lptr+opsize-1))
|
||||
return 1;
|
||||
if(*list) {
|
||||
++list;
|
||||
++opindex;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
|
||||
blanks() {
|
||||
while(1) {
|
||||
while(ch) {
|
||||
if(white()) gch();
|
||||
else return;
|
||||
}
|
||||
if(line == mline) return;
|
||||
preprocess();
|
||||
if(eof) break;
|
||||
}
|
||||
}
|
||||
|
||||
white() {
|
||||
return (*lptr <= ' ' && *lptr);
|
||||
}
|
||||
|
||||
gch() {
|
||||
int c;
|
||||
if(c = ch) bump(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
bump(n) int n; {
|
||||
if(n) lptr += n;
|
||||
else lptr = line;
|
||||
if(ch = nch = *lptr) nch = *(lptr+1);
|
||||
}
|
||||
|
||||
kill() {
|
||||
*line = 0;
|
||||
bump(0);
|
||||
}
|
||||
|
||||
skip() {
|
||||
if(an(inbyte()))
|
||||
while(an(ch)) gch();
|
||||
else while(an(ch) == 0) {
|
||||
if(ch == 0) break;
|
||||
gch();
|
||||
}
|
||||
blanks();
|
||||
}
|
||||
|
||||
endst() {
|
||||
blanks();
|
||||
return (streq(lptr, ";") || ch == 0);
|
||||
}
|
||||
|
||||
/*********** symbol table management functions ***********/
|
||||
|
||||
addsym(sname, id, type, size, value, lgpp, class)
|
||||
char *sname, id, type;
|
||||
int size, value, *lgpp, class;
|
||||
{
|
||||
if(lgpp == &glbptr)
|
||||
{
|
||||
if(cptr2 = findglb(sname))
|
||||
return cptr2;
|
||||
if(cptr == 0)
|
||||
{
|
||||
error("global symbol table overflow");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(locptr > (ENDLOC-SYMMAX))
|
||||
{
|
||||
error("local symbol table overflow");
|
||||
exit(ERRCODE);
|
||||
}
|
||||
cptr = *lgpp;
|
||||
}
|
||||
cptr[IDENT] = id;
|
||||
cptr[TYPE] = type;
|
||||
cptr[CLASS] = class;
|
||||
putint(size, cptr + SIZE, INTSIZE);
|
||||
putint(value, cptr + OFFSET, INTSIZE);
|
||||
cptr3 = cptr2 = cptr + NAME;
|
||||
while(an(*sname))
|
||||
*cptr2++ = *sname++;
|
||||
|
||||
if(lgpp == &locptr)
|
||||
{
|
||||
*cptr2 = cptr2 - cptr3; /* set length */
|
||||
*lgpp = ++cptr2;
|
||||
}
|
||||
return cptr;
|
||||
}
|
||||
|
||||
/*
|
||||
** search for symbol match
|
||||
** on return cptr points to slot found or empty slot
|
||||
*/
|
||||
search(sname, buf, len, end, max, off)
|
||||
char *sname, *buf, *end; int len, max, off; {
|
||||
cptr =
|
||||
cptr2 = buf+((hash(sname)%(max-1))*len);
|
||||
while(*cptr != NULL) {
|
||||
if(astreq(sname, cptr+off, NAMEMAX)) return 1;
|
||||
if((cptr = cptr+len) >= end) cptr = buf;
|
||||
if(cptr == cptr2) return (cptr = 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
hash(sname) char *sname; {
|
||||
int i, c;
|
||||
i = 0;
|
||||
while(c = *sname++) i = (i << 1) + c;
|
||||
return i;
|
||||
}
|
||||
|
||||
findglb(sname) char *sname; {
|
||||
if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME))
|
||||
return cptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
findloc(sname) char *sname; {
|
||||
cptr = locptr - 1; /* search backward for block locals */
|
||||
while(cptr > STARTLOC) {
|
||||
cptr = cptr - *cptr;
|
||||
if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
|
||||
cptr = cptr - NAME - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
nextsym(entry) char *entry; {
|
||||
entry = entry + NAME;
|
||||
while(*entry++ >= ' '); /* find length byte */
|
||||
return entry;
|
||||
}
|
||||
|
||||
/******** while queue management functions *********/
|
||||
|
||||
addwhile(ptr) int ptr[]; {
|
||||
int k;
|
||||
ptr[WQSP] = csp; /* and stk ptr */
|
||||
ptr[WQLOOP] = getlabel(); /* and looping label */
|
||||
ptr[WQEXIT] = getlabel(); /* and exit label */
|
||||
if(wqptr == WQMAX) {
|
||||
error("control statement nesting limit");
|
||||
exit(ERRCODE);
|
||||
}
|
||||
k = 0;
|
||||
while (k < WQSIZ) *wqptr++ = ptr[k++];
|
||||
}
|
||||
|
||||
readwhile(ptr) int *ptr; {
|
||||
if(ptr <= wq) {
|
||||
error("out of context");
|
||||
return 0;
|
||||
}
|
||||
else return (ptr - WQSIZ);
|
||||
}
|
||||
|
||||
delwhile() {
|
||||
if(wqptr > wq) wqptr -= WQSIZ;
|
||||
}
|
||||
|
||||
/****************** utility functions ********************/
|
||||
|
||||
/*
|
||||
** test if c is alphabetic
|
||||
*/
|
||||
alpha(c) char c; {
|
||||
return (isalpha(c) || c == '_');
|
||||
}
|
||||
|
||||
/*
|
||||
** test if given character is alphanumeric
|
||||
*/
|
||||
an(c) char c; {
|
||||
return (alpha(c) || isdigit(c));
|
||||
}
|
||||
|
||||
/*
|
||||
** return next avail internal label number
|
||||
*/
|
||||
getlabel() {
|
||||
return(++nxtlab);
|
||||
}
|
||||
|
||||
/*
|
||||
** get integer of length len from address addr
|
||||
** (byte sequence set by "putint")
|
||||
*/
|
||||
getint(addr, len) char *addr; int len; {
|
||||
int i;
|
||||
i = *(addr + --len); /* high order byte sign extended */
|
||||
while(len--) i = (i << 8) | *(addr + len) & 255;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
** put integer i of length len into address addr
|
||||
** (low byte first)
|
||||
*/
|
||||
putint(i, addr, len) char *addr; int i, len; {
|
||||
while(len--) {
|
||||
*addr++ = i;
|
||||
i = i >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
lout(line, fd) char *line; int fd; {
|
||||
fputs(line, fd);
|
||||
fputc(NEWLINE, fd);
|
||||
}
|
||||
|
||||
/******************* error functions *********************/
|
||||
|
||||
illname() {
|
||||
error("illegal symbol");
|
||||
skip();
|
||||
}
|
||||
|
||||
multidef(sname) char *sname; {
|
||||
error("already defined");
|
||||
}
|
||||
|
||||
needlval() {
|
||||
error("must be lvalue");
|
||||
}
|
||||
|
||||
noiferr() {
|
||||
error("no matching #if...");
|
||||
errflag = 0;
|
||||
}
|
||||
|
||||
error(msg)
|
||||
char msg[];
|
||||
{
|
||||
if(errflag)
|
||||
return;
|
||||
else
|
||||
errflag = 1;
|
||||
|
||||
lout(line, stderr);
|
||||
errout(msg, stderr);
|
||||
if(alarm)
|
||||
fputc(7, stderr);
|
||||
if(pause)
|
||||
while(fgetc(stderr) != NEWLINE);
|
||||
if(listfp > 0)
|
||||
errout(msg, listfp);
|
||||
}
|
||||
|
||||
errout(msg, fp) char msg[]; int fp; {
|
||||
int k;
|
||||
k = line+2;
|
||||
while(k++ <= lptr) fputc(' ', fp);
|
||||
lout("/\\", fp);
|
||||
fputs("**** ", fp); lout(msg, fp);
|
||||
}
|
||||
|
1093
programs/develop/scc/cc3.c
Normal file
1093
programs/develop/scc/cc3.c
Normal file
File diff suppressed because it is too large
Load Diff
985
programs/develop/scc/cc4.c
Normal file
985
programs/develop/scc/cc4.c
Normal file
@ -0,0 +1,985 @@
|
||||
/*
|
||||
** Small-C Compiler -- Part 4 -- Back End.
|
||||
** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
|
||||
** Copyright 1998 H T Walheim
|
||||
** All rights reserved.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "cc.h"
|
||||
|
||||
/* #define DISOPT */ /* display optimizations values */
|
||||
|
||||
/*************************** externals ****************************/
|
||||
|
||||
extern char
|
||||
*cptr, *macn, *litq, *symtab, optimize, ssname[NAMESIZE];
|
||||
|
||||
extern int
|
||||
*stage, litlab, litptr, csp, output, oldseg, usexpr,
|
||||
*snext, *stail, *slast;
|
||||
|
||||
|
||||
/***************** optimizer command definitions ******************/
|
||||
|
||||
/* -- p-codes must not overlap these */
|
||||
#define any 0x00FF /* matches any p-code */
|
||||
#define _pop 0x00FE /* matches if corresponding POP2 exists */
|
||||
#define pfree 0x00FD /* matches if pri register free */
|
||||
#define sfree 0x00FC /* matches if sec register free */
|
||||
#define comm 0x00FB /* matches if registers are commutative */
|
||||
|
||||
/* -- these digits are reserved for n */
|
||||
#define go 0x0100 /* go n entries */
|
||||
#define gc 0x0200 /* get code from n entries away */
|
||||
#define gv 0x0300 /* get value from n entries away */
|
||||
#define sum 0x0400 /* add value from nth entry away */
|
||||
#define neg 0x0500 /* negate the value */
|
||||
#define ife 0x0600 /* if value == n do commands to next 0 */
|
||||
#define ifl 0x0700 /* if value < n do commands to next 0 */
|
||||
#define swv 0x0800 /* swap value with value n entries away */
|
||||
#define topop 0x0900 /* moves |code and current value to POP2 */
|
||||
|
||||
#define p1 0x0001 /* plus 1 */
|
||||
#define p2 0x0002 /* plus 2 */
|
||||
#define p3 0x0003 /* plus 3 */
|
||||
#define p4 0x0004 /* plus 4 */
|
||||
#define m1 0x00FF /* minus 1 */
|
||||
#define m2 0x00FE /* minus 2 */
|
||||
#define m3 0x00FD /* minus 3 */
|
||||
#define m4 0x00FC /* minus 4 */
|
||||
|
||||
#define PRI 0030 /* primary register bits */
|
||||
#define SEC 0003 /* secondary register bits */
|
||||
#define USES 0011 /* use register contents */
|
||||
#define ZAPS 0022 /* zap register contents */
|
||||
#define PUSHES 0100 /* pushes onto the stack */
|
||||
#define COMMUTES 0200 /* commutative p-code */
|
||||
|
||||
/******************** optimizer command lists *********************/
|
||||
|
||||
int
|
||||
seq00[] = {0,ADD12,MOVE21,0, /* ADD21 */
|
||||
go|p1,ADD21,0},
|
||||
|
||||
seq01[] = {0,ADD1n,0, /* rINC1 or rDEC1 ? */
|
||||
ifl|m2,0,ifl|0,rDEC1,neg,0,ifl|p3,rINC1,0,0},
|
||||
|
||||
seq02[] = {0,ADD2n,0, /* rINC2 or rDEC2 ? */
|
||||
ifl|m2,0,ifl|0,rDEC2,neg,0,ifl|p3,rINC2,0,0},
|
||||
|
||||
seq03[] = {0,rDEC1,PUTbp1,rINC1,0, /* SUBbpn or DECbp */
|
||||
go|p2,ife|p1,DECbp,0,SUBbpn,0},
|
||||
|
||||
seq04[] = {0,rDEC1,PUTwp1,rINC1,0, /* SUBwpn or DECwp */
|
||||
go|p2,ife|p1,DECwp,0,SUBwpn,0},
|
||||
|
||||
seq05[] = {0,rDEC1,PUTbm1,rINC1,0, /* SUB_m_ COMMAn */
|
||||
go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
|
||||
|
||||
seq06[] = {0,rDEC1,PUTwm1,rINC1,0, /* SUB_m_ COMMAn */
|
||||
go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
|
||||
|
||||
seq07[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1p,0, /* GETw2m GETb1p */
|
||||
go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
|
||||
|
||||
seq08[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1pu,0, /* GETw2m GETb1pu */
|
||||
go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
|
||||
|
||||
seq09[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETw1p,0, /* GETw2m GETw1p */
|
||||
go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
|
||||
|
||||
seq10[] = {0,GETw1m,GETw2m,SWAP12,0, /* GETw2m GETw1m */
|
||||
go|p2,GETw1m,gv|m1,go|m1,gv|m1,0},
|
||||
|
||||
seq11[] = {0,GETw1m,MOVE21,0, /* GETw2m */
|
||||
go|p1,GETw2m,gv|m1,0},
|
||||
|
||||
seq12[] = {0,GETw1m,PUSH1,pfree,0, /* PUSHm */
|
||||
go|p1,PUSHm,gv|m1,0},
|
||||
|
||||
seq13[] = {0,GETw1n,PUTbm1,pfree,0, /* PUT_m_ COMMAn */
|
||||
PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
|
||||
|
||||
seq14[] = {0,GETw1n,PUTwm1,pfree,0, /* PUT_m_ COMMAn */
|
||||
PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
|
||||
|
||||
seq15[] = {0,GETw1p,PUSH1,pfree,0, /* PUSHp */
|
||||
go|p1,PUSHp,gv|m1,0},
|
||||
|
||||
seq16[] = {0,GETw1s,GETw2n,ADD12,MOVE21,0, /* GETw2s ADD2n */
|
||||
go|p3,ADD2n,gv|m2,go|m1,GETw2s,gv|m2,0},
|
||||
|
||||
seq17[] = {0,GETw1s,GETw2s,SWAP12,0, /* GETw2s GETw1s */
|
||||
go|p2,GETw1s,gv|m1,go|m1,GETw2s,gv|m1,0},
|
||||
|
||||
seq18[] = {0,GETw1s,MOVE21,0, /* GETw2s */
|
||||
go|p1,GETw2s,gv|m1,0},
|
||||
|
||||
seq19[] = {0,GETw2m,GETw1n,SWAP12,SUB12,0, /* GETw1m SUB1n */
|
||||
go|p3,SUB1n,gv|m2,go|m1,GETw1m,gv|m2,0},
|
||||
|
||||
seq20[] = {0,GETw2n,ADD12,0, /* ADD1n */
|
||||
go|p1,ADD1n,gv|m1,0},
|
||||
|
||||
seq21[] = {0,GETw2s,GETw1n,SWAP12,SUB12,0, /* GETw1s SUB1n */
|
||||
go|p3,SUB1n,gv|m2,go|m1,GETw1s,gv|m2,0},
|
||||
|
||||
seq22[] = {0,rINC1,PUTbm1,rDEC1,0, /* ADDm_ COMMAn */
|
||||
go|p1,ADDm_,go|p1,COMMAn,go|m1,0},
|
||||
|
||||
seq23[] = {0,rINC1,PUTwm1,rDEC1,0, /* ADDm_ COMMAn */
|
||||
go|p1,ADDm_,go|p1,COMMAn,go|m1,0},
|
||||
|
||||
seq24[] = {0,rINC1,PUTbp1,rDEC1,0, /* ADDbpn or INCbp */
|
||||
go|p2,ife|p1,INCbp,0,ADDbpn,0},
|
||||
|
||||
seq25[] = {0,rINC1,PUTwp1,rDEC1,0, /* ADDwpn or INCwp */
|
||||
go|p2,ife|p1,INCwp,0,ADDwpn,0},
|
||||
|
||||
seq26[] = {0,MOVE21,GETw1n,SWAP12,SUB12,0, /* SUB1n */
|
||||
go|p3,SUB1n,gv|m2,0},
|
||||
|
||||
seq27[] = {0,MOVE21,GETw1n,comm,0, /* GETw2n comm */
|
||||
go|p1,GETw2n,0},
|
||||
|
||||
seq28[] = {0,POINT1m,GETw2n,ADD12,MOVE21,0, /* POINT2m_ PLUSn */
|
||||
go|p3,PLUSn,gv|m2,go|m1,POINT2m_,gv|m2,0},
|
||||
|
||||
seq29[] = {0,POINT1m,MOVE21,pfree,0, /* POINT2m */
|
||||
go|p1,POINT2m,gv|m1,0},
|
||||
|
||||
seq30[] = {0,POINT1m,PUSH1,pfree,_pop,0, /* ... POINT2m */
|
||||
topop|POINT2m,go|p2,0},
|
||||
|
||||
seq31[] = {0,POINT1s,GETw2n,ADD12,MOVE21,0, /* POINT2s */
|
||||
sum|p1,go|p3,POINT2s,gv|m3,0},
|
||||
|
||||
seq32[] = {0,POINT1s,PUSH1,MOVE21,0, /* POINT2s PUSH2 */
|
||||
go|p1,POINT2s,gv|m1,go|p1,PUSH2,go|m1,0},
|
||||
|
||||
seq33[] = {0,POINT1s,PUSH1,pfree,_pop,0, /* ... POINT2s */
|
||||
topop|POINT2s,go|p2,0},
|
||||
|
||||
seq34[] = {0,POINT1s,MOVE21,0, /* POINT2s */
|
||||
go|p1,POINT2s,gv|m1,0},
|
||||
|
||||
seq35[] = {0,POINT2m,GETb1p,sfree,0, /* GETb1m */
|
||||
go|p1,GETb1m,gv|m1,0},
|
||||
|
||||
seq36[] = {0,POINT2m,GETb1pu,sfree,0, /* GETb1mu */
|
||||
go|p1,GETb1mu,gv|m1,0},
|
||||
|
||||
seq37[] = {0,POINT2m,GETw1p,sfree,0, /* GETw1m */
|
||||
go|p1,GETw1m,gv|m1,0},
|
||||
|
||||
seq38[] = {0,POINT2m_,PLUSn,GETw1p,sfree,0, /* GETw1m_ PLUSn */
|
||||
go|p2,gc|m1,gv|m1,go|m1,GETw1m_,gv|m1,0},
|
||||
|
||||
seq39[] = {0,POINT2s,GETb1p,sfree,0, /* GETb1s */
|
||||
sum|p1,go|p1,GETb1s,gv|m1,0},
|
||||
|
||||
seq40[] = {0,POINT2s,GETb1pu,sfree,0, /* GETb1su */
|
||||
sum|p1,go|p1,GETb1su,gv|m1,0},
|
||||
|
||||
seq41[] = {0,POINT2s,GETw1p,PUSH1,pfree,0, /* PUSHs */
|
||||
sum|p1,go|p2,PUSHs,gv|m2,0},
|
||||
|
||||
seq42[] = {0,POINT2s,GETw1p,sfree,0, /* GETw1s */
|
||||
sum|p1,go|p1,GETw1s,gv|m1,0},
|
||||
|
||||
seq43[] = {0,PUSH1,any,POP2,0, /* MOVE21 any */
|
||||
go|p2,gc|m1,gv|m1,go|m1,MOVE21,0},
|
||||
|
||||
seq44[] = {0,PUSHm,_pop,0, /* ... GETw2m */
|
||||
topop|GETw2m,go|p1,0},
|
||||
|
||||
seq45[] = {0,PUSHp,any,POP2,0, /* GETw2p ... */
|
||||
go|p2,gc|m1,gv|m1,go|m1,GETw2p,gv|m1,0},
|
||||
|
||||
seq46[] = {0,PUSHs,_pop,0, /* ... GETw2s */
|
||||
topop|GETw2s,go|p1,0},
|
||||
|
||||
seq47[] = {0,SUB1n,0, /* rDEC1 or rINC1 ? */
|
||||
ifl|m2,0,ifl|0,rINC1,neg,0,ifl|p3,rDEC1,0,0};
|
||||
|
||||
#define HIGH_SEQ 47
|
||||
int seq[HIGH_SEQ + 1];
|
||||
setseq() {
|
||||
seq[ 0] = seq00; seq[ 1] = seq01; seq[ 2] = seq02; seq[ 3] = seq03;
|
||||
seq[ 4] = seq04; seq[ 5] = seq05; seq[ 6] = seq06; seq[ 7] = seq07;
|
||||
seq[ 8] = seq08; seq[ 9] = seq09; seq[10] = seq10; seq[11] = seq11;
|
||||
seq[12] = seq12; seq[13] = seq13; seq[14] = seq14; seq[15] = seq15;
|
||||
seq[16] = seq16; seq[17] = seq17; seq[18] = seq18; seq[19] = seq19;
|
||||
seq[20] = seq20; seq[21] = seq21; seq[22] = seq22; seq[23] = seq23;
|
||||
seq[24] = seq24; seq[25] = seq25; seq[26] = seq26; seq[27] = seq27;
|
||||
seq[28] = seq28; seq[29] = seq29; seq[30] = seq30; seq[31] = seq31;
|
||||
seq[32] = seq32; seq[33] = seq33; seq[34] = seq34; seq[35] = seq35;
|
||||
seq[36] = seq36; seq[37] = seq37; seq[38] = seq38; seq[39] = seq39;
|
||||
seq[40] = seq40; seq[41] = seq41; seq[42] = seq42; seq[43] = seq43;
|
||||
seq[44] = seq44; seq[45] = seq45; seq[46] = seq46; seq[47] = seq47;
|
||||
}
|
||||
|
||||
/***************** assembly-code strings ******************/
|
||||
|
||||
int code[PCODES];
|
||||
|
||||
/*
|
||||
** First byte contains flag bits indicating:
|
||||
** the value in ax is needed (010) or zapped (020)
|
||||
** the value in bx is needed (001) or zapped (002)
|
||||
*/
|
||||
setcodes() {
|
||||
setseq();
|
||||
code[ADD12] = "\211ADD EAX,EBX\15\n";
|
||||
code[ADD1n] = "\010?ADD EAX,<n>\15\n??";
|
||||
code[ADD21] = "\211ADD EBX,EAX\15\n";
|
||||
code[ADD2n] = "\010?ADD EBX,<n>\15\n??";
|
||||
code[ADDbpn] = "\001ADD BYTE [EBX],<n>\15\n";
|
||||
code[ADDwpn] = "\001ADD WORD [EBX],<n>\15\n";
|
||||
code[ADDm_] = "\000ADD <m>";
|
||||
code[ADDSP] = "\000?ADD ESP,<n>\15\n??";
|
||||
code[AND12] = "\211AND EAX,EBX\15\n";
|
||||
code[ANEG1] = "\010NEG EAX\15\n";
|
||||
code[ARGCNTn] = "\000?MOV CL,<n>?XOR CL,CL?\15\n";
|
||||
code[ASL12] = "\011MOV ECX,EAX\15\nMOV EAX,EBX\15\nSAL EAX,CL\15\n";
|
||||
code[ASR12] = "\011MOV ECX,EAX\15\nMOV EAX,EBX\15\nSAR EAX,CL\15\n";
|
||||
code[CALL1] = "\010CALL EAX\15\n";
|
||||
code[CALLm] = "\020CALL <m>\15\n";
|
||||
code[BYTE_] = "\000 DB ";
|
||||
code[BYTEn] = "\000 RESB <n>\15\n";
|
||||
code[BYTEr0] = "\000 TIMES <n> DB 0\15\n";
|
||||
code[COM1] = "\010NOT EAX\15\n";
|
||||
code[COMMAn] = "\000,<n>\15\n";
|
||||
code[DBL1] = "\010SHL EAX,1\15\n";
|
||||
code[DBL2] = "\001SHL EBX,1\15\n";
|
||||
code[DECbp] = "\001DEC BYTE [EBX]\15\n";
|
||||
code[DECwp] = "\001DEC WORD [EBX]\15\n";
|
||||
code[DIV12] = "\011CDQ\15\nIDIV EBX\15\n"; /* see gen() */
|
||||
code[DIV12u] = "\011XOR EDX,EDX\15\nDIV EBX\15\n"; /* see gen() */
|
||||
|
||||
code[DWORD_] = "\000 DD ";
|
||||
code[DWORDn] = "\000 DD <n>\15\n";
|
||||
code[DWORDr0] = "\000 TIMES <n> DD 0\15\n";
|
||||
|
||||
code[ENTER] = "\100PUSH EBP\15\nMOV EBP,ESP\15\n";
|
||||
code[EQ10f] = "\010<g>OR EAX,EAX\15\nJE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
|
||||
code[EQ12] = "\211CALL __eq\15\n";
|
||||
code[GE10f] = "\010<g>OR EAX,EAX\15\nJGE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
|
||||
code[GE12] = "\011CALL __ge\15\n";
|
||||
code[GE12u] = "\011CALL __uge\15\n";
|
||||
code[GETb1m] = "\020MOVSX EAX,BYTE [<m>]\15\n";
|
||||
code[GETb1mu] = "\020MOVZX EAX,BYTE [<m>]\15\n";
|
||||
code[GETb1p] = "\021MOVSX EAX,BYTE [EBX?<o>??]\15\n"; /* see gen() */
|
||||
code[GETb1pu] = "\021MOVZX EAX,BYTE [EBX?<o>??]\15\n"; /* see gen() */
|
||||
code[GETb1s] = "\020MOVSX EAX,BYTE [EBP<o>]\15\n";
|
||||
code[GETb1su] = "\020MOVZX EAX,BYTE [EBP<o>]\15\n";
|
||||
|
||||
code[GETd1m] = "\020MOV EAX,[<m>]\15\n";
|
||||
code[GETd1n] = "\020?MOV EAX,<n>?XOR EAX,EAX?\15\n";
|
||||
code[GETd1p] = "\021MOV EAX, [EBX?<o>??]\15\n"; /* see gen() */
|
||||
code[GETd2n] = "\002?MOV EBX,<n>?XOR EBX,EBX?\15\n";
|
||||
|
||||
code[GETw1m] = "\020MOVSX EAX,WORD [<m>]\15\n";
|
||||
code[GETw1m_] = "\020MOVSX EAX,WORD [<m>]";
|
||||
code[GETw1n] = "\020?MOV EAX,<n>?XOR EAX,EAX?\15\n";
|
||||
code[GETw1p] = "\021MOVSX EAX, WORD [EBX?<o>??]\15\n"; /* see gen() */
|
||||
code[GETw1s] = "\020MOVSX EAX, WORD [EBP<o>]\15\n";
|
||||
code[GETw2m] = "\002MOVSX EBX,WORD <m>\15\n";
|
||||
code[GETw2n] = "\002?MOV EBX,<n>?XOR EBX,EBX?\15\n";
|
||||
code[GETw2p] = "\021MOVSX EBX,WORD [EBX?<o>??]\15\n";
|
||||
code[GETw2s] = "\002MOVSX EBX,WORD [EBP<o>]\15\n";
|
||||
code[GT10f] = "\010<g>OR EAX,EAX\15\nJG _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
|
||||
code[GT12] = "\010CALL __gt\15\n";
|
||||
code[GT12u] = "\011CALL __ugt\15\n";
|
||||
code[INCbp] = "\001INC BYTE [EBX]\15\n";
|
||||
code[INCwp] = "\001INC WORD [EBX]\15\n";
|
||||
code[WORD_] = "\000 DW ";
|
||||
code[WORDn] = "\000 RESW <n>\15\n";
|
||||
code[WORDr0] = "\000 TIMES <n> DW 0\15\n";
|
||||
code[JMPm] = "\000JMP _<n>\15\n";
|
||||
code[LABm] = "\000_<n>:\15\n";
|
||||
code[LE10f] = "\010<g>OR EAX,EAX\15\nJLE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
|
||||
code[LE12] = "\011CALL __le\15\n";
|
||||
code[LE12u] = "\011CALL __ule\15\n";
|
||||
code[LNEG1] = "\010CALL __lneg\15\n";
|
||||
code[LT10f] = "\010<g>OR EAX,EAX\15\nJL _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
|
||||
code[LT12] = "\011CALL __lt\15\n";
|
||||
code[LT12u] = "\011CALL __ult\15\n";
|
||||
code[MOD12] = "\011CDQ\15\nIDIV EBX\15\nMOV EAX,EDX\15\n"; /* see gen() */
|
||||
code[MOD12u] = "\011XOR EDX,EDX\15\nDIV EBX\15\nMOV EAX,EDX\15\n"; /* see gen() */
|
||||
code[MOVE21] = "\012MOV EBX,EAX\15\n";
|
||||
code[MUL12] = "\211IMUL EBX\15\n";
|
||||
code[MUL12u] = "\211MUL EBX\15\n";
|
||||
code[NE10f] = "\010<g>OR EAX,EAX\15\nJNE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
|
||||
code[NE12] = "\211CALL __ne\15\n";
|
||||
code[NEARm] = "\000 DD _<n>\15\n";
|
||||
code[OR12] = "\211OR EAX,EBX\15\n";
|
||||
code[PLUSn] = "\000?+<n>??\15\n";
|
||||
code[POINT1l] = "\020MOV EAX,_<l>+<n>\15\n";
|
||||
code[POINT1m] = "\020MOV EAX,<m>\15\n";
|
||||
code[POINT1s] = "\020LEA EAX,[EBP<o>]\15\n";
|
||||
code[POINT2m] = "\002MOV EBX,<m>\15\n";
|
||||
code[POINT2m_]= "\002MOV EBX,<m>";
|
||||
code[POINT2s] = "\002LEA EBX,[EBP<o>]\15\n";
|
||||
code[POP2] = "\002POP EBX\15\n";
|
||||
code[PUSH1] = "\110PUSH EAX\15\n";
|
||||
code[PUSH2] = "\101PUSH EBX\15\n";
|
||||
code[PUSHm] = "\100PUSH <m>\15\n";
|
||||
code[PUSHp] = "\100PUSH [EBX?<o>??]\15\n";
|
||||
code[PUSHs] = "\100PUSH [EBP?<o>??]\15\n";
|
||||
code[PUT_m_] = "\000MOV <m>";
|
||||
code[PUTbm1] = "\010MOV BYTE [<m>],AL\15\n";
|
||||
code[PUTbp1] = "\011MOV [EBX],AL\15\n";
|
||||
code[PUTdm1] = "\010MOV DWORD [<m>],EAX\15\n";
|
||||
code[PUTdp1] = "\011MOV [EBX],EAX\15\n";
|
||||
code[PUTwm1] = "\010MOV WORD [<m>],AX\15\n";
|
||||
code[PUTwp1] = "\011MOV [EBX],AX\15\n";
|
||||
code[rDEC1] = "\010#DEC EAX\15\n#";
|
||||
code[rDEC2] = "\010#DEC EBX\15\n#";
|
||||
code[REFm] = "\000_<n>";
|
||||
code[RETURN] = "\000?MOV ESP,EBP\15\n??POP EBP\15\nRET\15\n";
|
||||
code[rINC1] = "\010#INC EAX\15\n#";
|
||||
code[rINC2] = "\010#INC EBX\15\n#";
|
||||
code[SUB_m_] = "\000SUB <m>";
|
||||
code[SUB12] = "\011SUB EAX,EBX\15\n"; /* see gen() */
|
||||
code[SUB1n] = "\010?SUB EAX,<n>\15\n??";
|
||||
code[SUBbpn] = "\001SUB [EBX],<n>\15\n";
|
||||
code[SUBwpn] = "\001SUB [EBX],<n>\15\n";
|
||||
code[SWAP12] = "\011XCHG EAX,EBX\15\n";
|
||||
code[SWAP1s] = "\012POP EBX\15\nXCHG EAX,EBX\15\nPUSH EBX\15\n";
|
||||
code[SWITCH] = "\012CALL __switch\15\n";
|
||||
code[XOR12] = "\211XOR EAX,EBX\15\n";
|
||||
}
|
||||
|
||||
/***************** code generation functions *****************/
|
||||
|
||||
/*
|
||||
** print all assembler info before any code is generated
|
||||
** and ensure that the segments appear in the correct order.
|
||||
*/
|
||||
header() {
|
||||
/* outline(" .386");
|
||||
outline(" .MODEL FLAT");
|
||||
*/ toseg(CODESEG);
|
||||
|
||||
/* - FASM
|
||||
outline("EXTERN __eq");
|
||||
outline("EXTERN __ne");
|
||||
outline("EXTERN __le");
|
||||
outline("EXTERN __lt");
|
||||
outline("EXTERN __ge");
|
||||
outline("EXTERN __gt");
|
||||
outline("EXTERN __ule");
|
||||
outline("EXTERN __ult");
|
||||
outline("EXTERN __uge");
|
||||
outline("EXTERN __ugt");
|
||||
outline("EXTERN __lneg");
|
||||
outline("EXTERN __switch");
|
||||
*/
|
||||
|
||||
/* outline("dw 0"); *//* force non-zero code pointers, word alignment */
|
||||
toseg(DATASEG);
|
||||
/* outline("dw 0"); *//* force non-zero data pointers, word alignment */
|
||||
}
|
||||
|
||||
/*
|
||||
** print any assembler stuff needed at the end
|
||||
*/
|
||||
trailer() {
|
||||
char *cp;
|
||||
cptr = STARTGLB;
|
||||
while(cptr < ENDGLB) {
|
||||
if(cptr[IDENT] == FUNCTION && cptr[CLASS] == AUTOEXT)
|
||||
external(cptr + NAME, 0, FUNCTION);
|
||||
cptr += SYMMAX;
|
||||
}
|
||||
/*
|
||||
if((cp = findglb("main")) && cp[CLASS]==STATIC)
|
||||
external("_main", 0, FUNCTION);
|
||||
*/
|
||||
toseg(NULL);
|
||||
/* outline("END"); */
|
||||
#ifdef DISOPT
|
||||
{
|
||||
int i, *count;
|
||||
printf(";opt count\n");
|
||||
for(i = -1; ++i <= HIGH_SEQ; ) {
|
||||
count = seq[i];
|
||||
printf("; %2u %5u\n", i, *count);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** remember where we are in the queue in case we have to back up.
|
||||
*/
|
||||
setstage(before, start) int *before, *start; {
|
||||
if((*before = snext) == 0)
|
||||
snext = stage;
|
||||
*start = snext;
|
||||
}
|
||||
|
||||
/*
|
||||
** generate code in staging buffer.
|
||||
*/
|
||||
gen(pcode, value)
|
||||
int pcode, value;
|
||||
{
|
||||
int newcsp;
|
||||
switch(pcode)
|
||||
{
|
||||
case GETb1pu:
|
||||
case GETb1p:
|
||||
case GETw1p:
|
||||
case GETd1p:
|
||||
gen(MOVE21, 0);
|
||||
break;
|
||||
case SUB12:
|
||||
case MOD12:
|
||||
case MOD12u:
|
||||
case DIV12:
|
||||
case DIV12u:
|
||||
gen(SWAP12, 0);
|
||||
break;
|
||||
case PUSH1:
|
||||
#ifdef INT32
|
||||
csp -= BPD;
|
||||
#else
|
||||
csp -= BPW;
|
||||
#endif
|
||||
break;
|
||||
case POP2:
|
||||
#ifdef INT32
|
||||
csp += BPD;
|
||||
#else
|
||||
csp += BPW;
|
||||
#endif
|
||||
break;
|
||||
case ADDSP:
|
||||
case RETURN:
|
||||
newcsp = value;
|
||||
value -= csp;
|
||||
csp = newcsp;
|
||||
}
|
||||
if(snext == 0)
|
||||
{
|
||||
outcode(pcode, value);
|
||||
return;
|
||||
}
|
||||
if(snext >= slast)
|
||||
{
|
||||
error("staging buffer overflow");
|
||||
return;
|
||||
}
|
||||
snext[0] = pcode;
|
||||
snext[1] = value;
|
||||
snext += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
** dump the contents of the queue.
|
||||
** If start = 0, throw away contents.
|
||||
** If before != 0, don't dump queue yet.
|
||||
*/
|
||||
clearstage(before, start)
|
||||
int *before, *start;
|
||||
{
|
||||
if(before)
|
||||
{
|
||||
snext = before;
|
||||
return;
|
||||
}
|
||||
if(start)
|
||||
dumpstage();
|
||||
snext = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** dump the staging buffer
|
||||
*/
|
||||
dumpstage()
|
||||
{
|
||||
int i;
|
||||
stail = snext;
|
||||
snext = stage;
|
||||
while(snext < stail)
|
||||
{
|
||||
if(optimize)
|
||||
{
|
||||
restart:
|
||||
i = -1;
|
||||
while(++i <= HIGH_SEQ)
|
||||
if(peep(seq[i]))
|
||||
{
|
||||
#ifdef DISOPT
|
||||
if(isatty(output))
|
||||
fprintf(stderr, " optimized %2u\n", i);
|
||||
#endif
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
outcode(snext[0], snext[1]);
|
||||
snext += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** change to a new segment
|
||||
** may be called with NULL, CODESEG, or DATASEG
|
||||
** With NASM the section names are case-sensitive
|
||||
*/
|
||||
toseg(newseg)
|
||||
int newseg;
|
||||
{
|
||||
if(oldseg == newseg)
|
||||
return;
|
||||
/* if(oldseg == CODESEG)
|
||||
outline("_TEXT ENDS");
|
||||
else if(oldseg == DATASEG)
|
||||
outline("_DATA ENDS"); <-- */
|
||||
|
||||
/* - FASM
|
||||
if(newseg == CODESEG)
|
||||
{
|
||||
outline("SECTION .text");
|
||||
}
|
||||
else if(newseg == DATASEG)
|
||||
outline("SECTION .data");
|
||||
*/
|
||||
oldseg = newseg;
|
||||
}
|
||||
|
||||
/*
|
||||
** declare entry point
|
||||
*/
|
||||
public(ident) int ident;{
|
||||
if(ident == FUNCTION)
|
||||
toseg(CODESEG);
|
||||
else toseg(DATASEG);
|
||||
/* - FASM
|
||||
outstr("GLOBAL ");
|
||||
outname(ssname);
|
||||
*/
|
||||
newline();
|
||||
outname(ssname);
|
||||
if(ident == FUNCTION) {
|
||||
colon();
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** declare external reference
|
||||
*/
|
||||
external(name, size, ident) char *name; int size, ident; {
|
||||
if(ident == FUNCTION)
|
||||
toseg(CODESEG);
|
||||
else toseg(DATASEG);
|
||||
/* - FASM
|
||||
outstr("EXTERN ");
|
||||
outname(name);
|
||||
/# colon();
|
||||
outsize(size, ident); <-- #/
|
||||
newline();
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
** output the size of the object pointed to.
|
||||
*/
|
||||
outsize(size, ident) int size, ident;
|
||||
{
|
||||
/* why not size on FUNCTION and POINTER ? */
|
||||
if (ident == FUNCTION)
|
||||
outstr("NEAR");
|
||||
else if (ident == POINTER)
|
||||
outstr("DWORD");
|
||||
else if(size == 1)
|
||||
outstr("BYTE");
|
||||
else if(size == 2)
|
||||
outstr("WORD");
|
||||
else
|
||||
outstr("DWORD");
|
||||
}
|
||||
|
||||
/*
|
||||
** point to following object(s)
|
||||
*/
|
||||
point() {
|
||||
outline(" DW $+2");
|
||||
}
|
||||
|
||||
/*
|
||||
** dump the literal pool
|
||||
*/
|
||||
dumplits(size) int size;
|
||||
{
|
||||
int j, k;
|
||||
k = 0;
|
||||
while (k < litptr)
|
||||
{
|
||||
if(size == 1)
|
||||
{
|
||||
gen(BYTE_, NULL);
|
||||
}
|
||||
else if (size == 2)
|
||||
{
|
||||
gen(WORD_, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gen(DWORD_,NULL);
|
||||
}
|
||||
j = 10;
|
||||
while(j--)
|
||||
{
|
||||
outdec(getint(litq + k, size));
|
||||
k += size;
|
||||
if(j == 0 || k >= litptr)
|
||||
{
|
||||
newline();
|
||||
break;
|
||||
}
|
||||
fputc(',', output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** dump zeroes for default initial values
|
||||
*/
|
||||
dumpzero(size, count)
|
||||
int size, count;
|
||||
{
|
||||
if(count > 0)
|
||||
{
|
||||
if(size == 1)
|
||||
gen(BYTEr0, count);
|
||||
else if (size == 2)
|
||||
gen(WORDr0, count);
|
||||
else
|
||||
gen(DWORDr0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/******************** optimizer functions ***********************/
|
||||
|
||||
/*
|
||||
** Try to optimize sequence at snext in the staging buffer.
|
||||
*/
|
||||
peep(seq) int *seq; {
|
||||
int *next, *count, *pop, n, skip, tmp, reply;
|
||||
char c;
|
||||
next = snext;
|
||||
count = seq++;
|
||||
while(*seq) {
|
||||
switch(*seq) {
|
||||
case any: if(next < stail) break; return (NO);
|
||||
case pfree: if(isfree(PRI, next)) break; return (NO);
|
||||
case sfree: if(isfree(SEC, next)) break; return (NO);
|
||||
case comm: if(*next & COMMUTES) break; return (NO);
|
||||
case _pop: if(pop = getpop(next)) break; return (NO);
|
||||
default: if(next >= stail || *next != *seq) return (NO);
|
||||
}
|
||||
next += 2; ++seq;
|
||||
}
|
||||
|
||||
/****** have a match, now optimize it ******/
|
||||
|
||||
*count += 1;
|
||||
reply = skip = NO;
|
||||
while(*(++seq) || skip) {
|
||||
if(skip) {
|
||||
if(*seq == 0) skip = NO;
|
||||
continue;
|
||||
}
|
||||
if(*seq >= PCODES) {
|
||||
c = *seq & 0xFF; /* get low byte of command */
|
||||
n = c; /* and sign extend into n */
|
||||
switch(*seq & 0xFF00) {
|
||||
case ife: if(snext[1] != n) skip = YES; break;
|
||||
case ifl: if(snext[1] >= n) skip = YES; break;
|
||||
case go: snext += (n<<1); break;
|
||||
case gc: snext[0] = snext[(n<<1)]; goto done;
|
||||
case gv: snext[1] = snext[(n<<1)+1]; goto done;
|
||||
case sum: snext[1] += snext[(n<<1)+1]; goto done;
|
||||
case neg: snext[1] = -snext[1]; goto done;
|
||||
case topop: pop[0] = n; pop[1] = snext[1]; goto done;
|
||||
case swv: tmp = snext[1];
|
||||
snext[1] = snext[(n<<1)+1];
|
||||
snext[(n<<1)+1] = tmp;
|
||||
done: reply = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else snext[0] = *seq; /* set p-code */
|
||||
}
|
||||
return (reply);
|
||||
}
|
||||
|
||||
/*
|
||||
** Is the primary or secondary register free?
|
||||
** Is it zapped or unused by the p-code at pp
|
||||
** or a successor? If the primary register is
|
||||
** unused by it still may not be free if the
|
||||
** context uses the value of the expression.
|
||||
*/
|
||||
isfree(reg, pp) int reg, *pp; {
|
||||
char *cp;
|
||||
while(pp < stail) {
|
||||
cp = code[*pp];
|
||||
if(*cp & USES & reg) return (NO);
|
||||
if(*cp & ZAPS & reg) return (YES);
|
||||
pp += 2;
|
||||
}
|
||||
if(usexpr) return (reg & 001); /* PRI => NO, SEC => YES at end */
|
||||
else return (YES);
|
||||
}
|
||||
|
||||
/*
|
||||
** Get place where the currently pushed value is popped?
|
||||
** NOTE: Function arguments are not popped, they are
|
||||
** wasted with an ADDSP.
|
||||
*/
|
||||
getpop(next) int *next; {
|
||||
char *cp;
|
||||
int level; level = 0;
|
||||
while(YES) {
|
||||
if(next >= stail) /* compiler error */
|
||||
return 0;
|
||||
if(*next == POP2)
|
||||
if(level) --level;
|
||||
else return next; /* have a matching POP2 */
|
||||
else if(*next == ADDSP) { /* after func call */
|
||||
if((level -= (next[1]>>LBPW)) < 0)
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
cp = code[*next]; /* code string ptr */
|
||||
if(*cp & PUSHES) ++level; /* must be a push */
|
||||
}
|
||||
next += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/******************* output functions *********************/
|
||||
|
||||
colon() {
|
||||
fputc(':', output);
|
||||
}
|
||||
|
||||
newline() {
|
||||
fputc('\15', output);
|
||||
fputc(NEWLINE, output);
|
||||
}
|
||||
|
||||
/*
|
||||
** output assembly code.
|
||||
**
|
||||
*/
|
||||
outcode(pcode, value)
|
||||
int pcode, value;
|
||||
{
|
||||
int part, skip, count;
|
||||
int byte_opt;
|
||||
char *cp, *back;
|
||||
int loc_label;
|
||||
part = back = 0;
|
||||
skip = NO;
|
||||
byte_opt = 0;
|
||||
|
||||
cp = code[pcode] + 1; /* skip 1st byte of code string */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
switch (pcode)
|
||||
{
|
||||
case BYTE_:
|
||||
case BYTEn:
|
||||
case BYTEr0:
|
||||
case WORD_:
|
||||
case WORDn:
|
||||
case WORDr0:
|
||||
case DWORD_:
|
||||
case DWORDn:
|
||||
case DWORDr0:
|
||||
case REFm:
|
||||
case COMMAn:
|
||||
case PLUSn:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
dump_debug (pcode, value);
|
||||
outtab ();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pcode == ADD1n)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
pcode = SUB1n;
|
||||
value = -value;
|
||||
}
|
||||
if (value < 128)
|
||||
{
|
||||
byte_opt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
while(*cp)
|
||||
{
|
||||
if(*cp == '<')
|
||||
{
|
||||
++cp; /* skip to action code */
|
||||
if(skip == NO)
|
||||
switch(*cp)
|
||||
{
|
||||
case 'm':
|
||||
outname(value+NAME);
|
||||
break; /* mem ref by label */
|
||||
case 'n':
|
||||
if (byte_opt)
|
||||
{
|
||||
outstr ("BYTE ");
|
||||
}
|
||||
outdec(value);
|
||||
break; /* numeric constant */
|
||||
case 'o':
|
||||
offset(value);
|
||||
break; /* numeric constant */
|
||||
case 'l':
|
||||
outdec(litlab);
|
||||
break; /* current literal label */
|
||||
case 'g': /* generate local label */
|
||||
loc_label = getlabel ();
|
||||
break;
|
||||
case 'd': /* dump local label */
|
||||
outdec(loc_label);
|
||||
break;
|
||||
}
|
||||
cp += 2; /* skip past > */
|
||||
}
|
||||
else if(*cp == '?') /* ?..if value...?...if not value...? */
|
||||
{
|
||||
switch(++part)
|
||||
{
|
||||
case 1:
|
||||
if(value == 0)
|
||||
skip = YES;
|
||||
break;
|
||||
case 2:
|
||||
skip = !skip;
|
||||
break;
|
||||
case 3:
|
||||
part = 0;
|
||||
skip = NO;
|
||||
break;
|
||||
}
|
||||
++cp; /* skip past ? */
|
||||
}
|
||||
else if(*cp == '#')
|
||||
{ /* repeat #...# value times */
|
||||
++cp;
|
||||
if(back == 0)
|
||||
{
|
||||
if((count = value) < 1)
|
||||
{
|
||||
while(*cp && *cp++ != '#')
|
||||
;
|
||||
continue;
|
||||
}
|
||||
back = cp;
|
||||
continue;
|
||||
}
|
||||
if(--count > 0)
|
||||
cp = back;
|
||||
else
|
||||
back = 0;
|
||||
}
|
||||
else if(skip == NO)
|
||||
fputc(*cp++, output);
|
||||
else
|
||||
++cp;
|
||||
}
|
||||
}
|
||||
|
||||
outdec(number) int number; {
|
||||
int k, zs;
|
||||
char c, *q, *r;
|
||||
zs = 0;
|
||||
k = 1000000000;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// fprintf(output, "/* %d */", number);
|
||||
#endif
|
||||
|
||||
if(number < 0) {
|
||||
number = -number;
|
||||
fputc('-', output);
|
||||
}
|
||||
|
||||
while (k >= 1) {
|
||||
q = 0;
|
||||
r = number;
|
||||
while(r >= k) {++q; r = r - k;}
|
||||
c = q + '0';
|
||||
if(c != '0' || k == 1 || zs) {
|
||||
zs = 1;
|
||||
fputc(c, output);
|
||||
}
|
||||
number = r;
|
||||
k /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
offset(number)
|
||||
int number;
|
||||
{
|
||||
int k, zs;
|
||||
char c, *q, *r;
|
||||
zs = 0;
|
||||
k = 1000000000;
|
||||
if(number < 0) {
|
||||
number = -number;
|
||||
fputc('-', output);
|
||||
}
|
||||
else
|
||||
{
|
||||
fputc('+',output);
|
||||
}
|
||||
|
||||
while (k >= 1) {
|
||||
q = 0;
|
||||
r = number;
|
||||
while(r >= k) {++q; r = r - k;}
|
||||
c = q + '0';
|
||||
if(c != '0' || k == 1 || zs) {
|
||||
zs = 1;
|
||||
fputc(c, output);
|
||||
}
|
||||
number = r;
|
||||
k /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
outline(ptr) char ptr[]; {
|
||||
outstr(ptr);
|
||||
newline();
|
||||
}
|
||||
|
||||
outname(ptr) char ptr[]; {
|
||||
outstr("_");
|
||||
while(*ptr >= ' ') fputc(*ptr++, output);
|
||||
}
|
||||
|
||||
outstr(ptr) char ptr[]; {
|
||||
while(*ptr == '\t' || *ptr >= ' ') fputc(*ptr++, output);
|
||||
}
|
||||
|
||||
outtab ()
|
||||
{
|
||||
fputc ('\t', output);
|
||||
}
|
Loading…
Reference in New Issue
Block a user