Rewrite gets in assembler

+19 bytes if used alone, because it pulls in fgets, but as code is
factorized, -128 bytes in programs using both fgets and gets.
This commit is contained in:
Colin Leroy-Mira 2024-01-11 19:51:17 +01:00
parent 65937684a0
commit aa6f850b8d
3 changed files with 93 additions and 63 deletions

View File

@ -1,63 +0,0 @@
/*
** gets.c
**
** Ullrich von Bassewitz, 11.08.1998
*/
#include <stdio.h>
#include "_file.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* __fastcall__ gets (char* s)
{
register char* p = s;
int c;
unsigned i = 0;
while (1) {
/* Get next character */
if ((c = fgetc (stdin)) == EOF) {
/* Error or EOF */
*p = '\0';
if (stdin->f_flags & _FERROR) {
/* ERROR */
return 0;
} else {
/* EOF */
if (i) {
return s;
} else {
return 0;
}
}
}
/* One char more. Newline ends the input */
if ((char) c == '\n') {
*p = '\0';
break;
} else {
*p = c;
++p;
++i;
}
}
/* Done */
return s;
}

47
libsrc/common/gets.s Normal file
View File

@ -0,0 +1,47 @@
;
; Colin Leroy-Mira, 2024
;
; char* __fastcall__ gets (char* s)
;
.export _gets
.import _fgets, _stdin, popax, pushax
.importzp ptr4
_gets:
; Push buffer
sta ptr4
stx ptr4+1
jsr pushax
; Push size (there's no limit!)
lda #$FF
tax
jsr pushax
lda _stdin
ldx _stdin+1
jsr _fgets
; Check return value
bne :+
cpx #$00
bne :+
rts
: ; At least one byte written.
jsr pushax ; Store returned pointer
; Remove \n if there is one.
lda ptr4 ; _fgets returns with ptr4 at
bne :+ ; end of buffer
dec ptr4+1
: dec ptr4
lda (ptr4),y ; _fgets returns with Y=0
cmp #$0A
bne :+
tya
sta (ptr4),y ; Set terminator over \n
: jmp popax

46
test/ref/test_gets.c Normal file
View File

@ -0,0 +1,46 @@
/*
!!DESCRIPTION!! gets test
!!LICENCE!! Public domain
*/
#include "common.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
char buf[512];
#define INFILE "cf.in"
#ifndef __CC65__
/* Force declaration on host compiler, as gets() is deprecated for
* being dangerous as hell */
char *gets (char *__s);
#endif
#ifdef NO_OLD_FUNC_DECL
int main(int argc,char **argv)
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
/* Fake stdin with the reference file */
fclose(stdin);
stdin = fopen(INFILE, "r");
if (stdin == NULL) {
return EXIT_FAILURE;
}
while (gets(buf) != NULL)
{
printf("%s",buf);
}
fclose(stdin);
return 0;
}