From 560689c0928b7e0822f8945930c6f39818395e54 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 10 Aug 2025 23:43:09 +0300 Subject: [PATCH] Add an empty cstdlib.elna source file --- source/CommandLineInterface.elna | 26 ++++---- source/Common.elna | 1 - source/Compiler.elna | 74 --------------------- source/Lexer.elna | 10 +-- source/Parser.elna | 12 ++-- source/Transpiler.elna | 110 +++++++++++++++---------------- source/cctype.elna | 11 ++++ source/cstdio.elna | 23 +++++++ source/cstdlib.elna | 13 ++++ source/cstring.elna | 13 ++++ source/main.elna | 57 +++------------- 11 files changed, 146 insertions(+), 204 deletions(-) delete mode 100644 source/Compiler.elna create mode 100644 source/cctype.elna create mode 100644 source/cstdio.elna create mode 100644 source/cstdlib.elna create mode 100644 source/cstring.elna diff --git a/source/CommandLineInterface.elna b/source/CommandLineInterface.elna index feca658..a5985b3 100644 --- a/source/CommandLineInterface.elna +++ b/source/CommandLineInterface.elna @@ -6,9 +6,7 @@ module; from Args import GetArg, Narg; from FIO import WriteString, WriteChar, WriteLine, StdErr; from Strings import CompareStr, Length; -from MemUtils import MemZero; - -from Common import ShortString; +import cstdlib, Common; type CommandLine = record @@ -29,26 +27,26 @@ begin NEW(result); result^.lex := false; result^.parse := false; - MemZero(@result^.input, 256); + memset(@result^.input, 0, 256); result^.output[1] := CHAR(0); while (i < Narg()) & (result <> nil) do parsed := GetArg(parameter, i); parsed := false; - if CompareStr(parameter, '--lex') = 0 then + if CompareStr(parameter, "--lex") = 0 then parsed := true; result^.lex := true end; - if CompareStr(parameter, '--parse') = 0 then + if CompareStr(parameter, "--parse") = 0 then parsed := true; result^.parse := true end; - if CompareStr(parameter, '-o') = 0 then + if CompareStr(parameter, "-o") = 0 then i := i + 1u; if i = Narg() then - WriteString(StdErr, 'Fatal error: expecting a file name following -o.'); + WriteString(StdErr, "Fatal error: expecting a file name following -o."); result := nil end; if i < Narg() then @@ -57,15 +55,15 @@ begin end; parsed := true end; - if (parameter[1] <> '-') & (parsed = false) then + if (parameter[1] <> "-") & (parsed = false) then parsed := true; if Length(result^.input) > 0 then - WriteString(StdErr, 'Fatal error: only one source file can be compiled at once. First given "'); + WriteString(StdErr, "Fatal error: only one source file can be compiled at once. First given \""); WriteString(StdErr, result^.input); - WriteString(StdErr, '", then "'); + WriteString(StdErr, "\", then \""); WriteString(StdErr, parameter); - WriteString(StdErr, '".'); + WriteString(StdErr, "\"."); WriteLine(StdErr); result := nil end; @@ -74,7 +72,7 @@ begin end end; if parsed = false then - WriteString(StdErr, 'Fatal error: unknown command line options: '); + WriteString(StdErr, "Fatal error: unknown command line options: "); WriteString(StdErr, parameter); WriteChar(StdErr, '.'); @@ -86,7 +84,7 @@ begin i := i + 1 end; if (result <> nil) & (Length(result^.input) = 0) then - WriteString(StdErr, 'Fatal error: no input files.'); + WriteString(StdErr, "Fatal error: no input files."); WriteLine(StdErr); result := nil end; diff --git a/source/Common.elna b/source/Common.elna index 627c972..a329baf 100644 --- a/source/Common.elna +++ b/source/Common.elna @@ -10,6 +10,5 @@ type line: Word; column: Word end; - FILE* = record end; end. diff --git a/source/Compiler.elna b/source/Compiler.elna deleted file mode 100644 index 8e410f0..0000000 --- a/source/Compiler.elna +++ /dev/null @@ -1,74 +0,0 @@ -(* This Source Code Form is subject to the terms of the Mozilla Public License, - v. 2.0. If a copy of the MPL was not distributed with this file, You can - obtain one at https://mozilla.org/MPL/2.0/. *) -program; - -from FIO import Close, IsNoError, File, OpenToRead, OpenToWrite, StdErr, StdOut, WriteLine, WriteString; -from M2RTS import HALT, ExitOnHalt; - -from Lexer import Lexer, lexer_destroy, lexer_initialize; -from Transpiler import transpile; -from CommandLineInterface import CommandLine, parse_command_line; -from Parser import AstModule, parse; -from Strings import Length; - -var - command_line: ^CommandLine; - -proc compile_from_stream(); -var - lexer: Lexer; - source_input: File; - source_output: File; - ast_module: ^AstModule; -begin - source_input := OpenToRead(command_line^.input); - - if IsNoError(source_input) = false then - WriteString(StdErr, 'Fatal error: failed to read the input file "'); - WriteString(StdErr, command_line^.input); - WriteString(StdErr, '".'); - WriteLine(StdErr); - - ExitOnHalt(2) - end; - source_output := nil; - - if Length(command_line^.output) > 0 then - source_output := OpenToWrite(command_line^.output); - - if IsNoError(source_output) = false then - WriteString(StdErr, 'Fatal error: failed to create the output file "'); - WriteString(StdErr, command_line^.output); - WriteString(StdErr, '".'); - WriteLine(StdErr); - - ExitOnHalt(2) - end - end; - - if IsNoError(source_input) then - lexer_initialize(@lexer, source_input); - - ast_module := parse(@lexer); - transpile(ast_module, StdOut, source_output, command_line^.input); - - lexer_destroy(@lexer); - - Close(source_output); - Close(source_input) - end -end; - -begin - ExitOnHalt(0); - command_line := parse_command_line(); - - if command_line <> nil then - compile_from_stream() - end; - if command_line = nil then - ExitOnHalt(1) - end; - HALT() -end. diff --git a/source/Lexer.elna b/source/Lexer.elna index 219502e..d39da5d 100644 --- a/source/Lexer.elna +++ b/source/Lexer.elna @@ -3,7 +3,7 @@ obtain one at https://mozilla.org/MPL/2.0/. *) module; -import Common, cstdlib; +import cstdio, Common; const CHUNK_SIZE := 85536; @@ -410,7 +410,7 @@ begin if lexer^.start.iterator^ = '"' then text_length := lexer^.current.iterator - lexer^.start.iterator + 1; - MemZero(@token^.stringKind, #size(ShortString)); + memset(@token^.stringKind, 0, #size(ShortString)); MemCopy(lexer^.start.iterator, text_length, @token^.stringKind); token^.kind := LexerKind.character @@ -418,7 +418,7 @@ begin if lexer^.start.iterator^ = "'" then text_length := lexer^.current.iterator - lexer^.start.iterator + 1; - MemZero(@token^.stringKind, #size(ShortString)); + memset(@token^.stringKind, 0, #size(ShortString)); MemCopy(lexer^.start.iterator, text_length, @token^.stringKind); token^.kind := LexerKind.string @@ -590,7 +590,7 @@ begin token^.kind := LexerKind.integer; integer_length := lexer^.current.iterator - lexer^.start.iterator; - MemZero(@token^.identifierKind, #size(Identifier)); + memset(@token^.identifierKind, 0, #size(Identifier)); MemCopy(lexer^.start.iterator, integer_length, @token^.identifierKind[1]); buffer := InitStringCharStar(@token^.identifierKind[1]); @@ -889,7 +889,7 @@ begin lexer^.length := 0; lexer^.buffer := malloc(CHUNK_SIZE); - MemZero(lexer^.buffer, CHUNK_SIZE); + memset(lexer^.buffer, 0, CHUNK_SIZE); lexer^.size := CHUNK_SIZE end; diff --git a/source/Parser.elna b/source/Parser.elna index a1fd45d..041dafd 100644 --- a/source/Parser.elna +++ b/source/Parser.elna @@ -3,11 +3,7 @@ obtain one at https://mozilla.org/MPL/2.0/. *) module; -import cstdlib; -from MemUtils import MemZero; - -from Common import Identifier, ShortString; -from Lexer import Lexer, LexerToken, lexer_current, lexer_lex; +import cstdlib, Common, Lexer; type Parser = record @@ -237,7 +233,7 @@ begin end end; current_field := current_field + 1; - MemZero(current_field, #size(AstFieldDeclaration)); + memset(current_field, 0, #size(AstFieldDeclaration)); return field_declarations end; @@ -331,7 +327,7 @@ begin token := parser_lex(parser^.lexer) end; current_case := current_case + 1; - MemZero(current_case, #size(Identifier)); + memset(current_case, 0, #size(Identifier)); return result end; @@ -608,7 +604,7 @@ begin token := parser_lex(parser^.lexer) end; current_symbol := current_symbol + 1; - MemZero(current_symbol, #size(Identifier)); + memset(current_symbol, 0, #size(Identifier)); token := parser_lex(parser^.lexer); diff --git a/source/Transpiler.elna b/source/Transpiler.elna index ae14a07..82dd788 100644 --- a/source/Transpiler.elna +++ b/source/Transpiler.elna @@ -6,7 +6,7 @@ module; from FIO import File, WriteNBytes, WriteLine, WriteChar, WriteString; from NumberIO import IntToStr; -from Common import Identifier, ShortString; +import Common; from Parser import AstLiteralKind, AstUnaryOperator, AstBinaryOperator, AstModule, AstExpression, AstLiteral, AstConstantDeclaration, AstStatement, AstTypedDeclaration, AstCompoundStatement, AstProcedureDeclaration, AstVariableDeclaration, AstImportStatement, AstTypeExpression, AstFieldDeclaration; @@ -26,7 +26,7 @@ begin count := 0; while count < context^.indentation do - WriteString(context^.output, ' '); + WriteString(context^.output, " "); count := count + 1u end end; @@ -43,17 +43,17 @@ var written_bytes: Word; current_symbol: ^Identifier; begin - WriteString(context^.output, 'FROM '); + WriteString(context^.output, "FROM "); written_bytes := WriteNBytes(context^.output, ORD(import_statement^.package[1]), @import_statement^.package[2]); - WriteString(context^.output, ' IMPORT '); + WriteString(context^.output, " IMPORT "); current_symbol := import_statement^.symbols; written_bytes := WriteNBytes(context^.output, ORD(current_symbol^[1]), @current_symbol^[2]); current_symbol := current_symbol + 1; while ORD(current_symbol^[1]) <> 0 do - WriteString(context^.output, ', '); + WriteString(context^.output, ", "); written_bytes := WriteNBytes(context^.output, ORD(current_symbol^[1]), @current_symbol^[2]); current_symbol := current_symbol + 1; end; @@ -76,10 +76,10 @@ var buffer: [20]CHAR; written_bytes: Word; begin - WriteString(context^.output, ' '); + WriteString(context^.output, " "); written_bytes := WriteNBytes(context^.output, ORD(declaration^.constant_name[1]), @declaration^.constant_name[2]); - WriteString(context^.output, ' = '); + WriteString(context^.output, " = "); IntToStr(declaration^.constant_value, 0, buffer); WriteString(context^.output, buffer); @@ -92,7 +92,7 @@ var current_declaration: ^^AstConstantDeclaration; begin if declarations^ <> nil then - WriteString(context^.output, 'CONST'); + WriteString(context^.output, "CONST"); WriteLine(context^.output); current_declaration := declarations; @@ -110,9 +110,9 @@ end; proc transpile_module(context: ^TranspilerContext, result: ^AstModule); begin if result^.main = false then - WriteString(context^.output, 'IMPLEMENTATION ') + WriteString(context^.output, "IMPLEMENTATION ") end; - WriteString(context^.output, 'MODULE '); + WriteString(context^.output, "MODULE "); (* Write the module name and end the line with a semicolon and newline. *) transpile_module_name(context); @@ -129,10 +129,10 @@ begin transpile_procedure_part(context, result^.procedures); transpile_statement_part(context, result^.statements); - WriteString(context^.output, 'END '); + WriteString(context^.output, "END "); transpile_module_name(context); - WriteChar(context^.output, '.'); + WriteChar(context^.output, "."); WriteLine(context^.output) end; @@ -144,10 +144,10 @@ begin current_field := fields; while ORD(current_field^.field_name[1]) <> 0 do - WriteString(context^.output, ' '); + WriteString(context^.output, " "); written_bytes := WriteNBytes(context^.output, ORD(current_field^.field_name[1]), @current_field^.field_name[2]); - WriteString(context^.output, ': '); + WriteString(context^.output, ": "); transpile_type_expression(context, current_field^.field_type); current_field := current_field + 1; @@ -161,15 +161,15 @@ end; proc transpile_record_type(context: ^TranspilerContext, type_expression: ^AstTypeExpression); begin - WriteString(context^.output, 'RECORD'); + WriteString(context^.output, "RECORD"); WriteLine(context^.output); transpile_type_fields(context, type_expression^.fields); - WriteString(context^.output, ' END') + WriteString(context^.output, " END") end; proc transpile_pointer_type(context: ^TranspilerContext, type_expression: ^AstTypeExpression); begin - WriteString(context^.output, 'POINTER TO '); + WriteString(context^.output, "POINTER TO "); transpile_type_expression(context, type_expression^.target) end; @@ -178,17 +178,17 @@ proc transpile_array_type(context: ^TranspilerContext, type_expression: ^AstType var buffer: [20]CHAR; begin - WriteString(context^.output, 'ARRAY'); + WriteString(context^.output, "ARRAY"); if type_expression^.length <> 0 then - WriteString(context^.output, '[1..'); + WriteString(context^.output, "[1.."); IntToStr(type_expression^.length, 0, buffer); WriteString(context^.output, buffer); WriteChar(context^.output, ']') end; - WriteString(context^.output, ' OF '); + WriteString(context^.output, " OF "); transpile_type_expression(context, type_expression^.base) end; @@ -200,22 +200,22 @@ var begin current_case := type_expression^.cases; - WriteString(context^.output, '('); + WriteString(context^.output, "("); WriteLine(context^.output); - WriteString(context^.output, ' '); + WriteString(context^.output, " "); written_bytes := WriteNBytes(context^.output, ORD(current_case^[1]), @current_case^[2]); current_case := current_case + 1; while ORD(current_case^[1]) <> 0 do WriteChar(context^.output, ','); WriteLine(context^.output); - WriteString(context^.output, ' '); + WriteString(context^.output, " "); written_bytes := WriteNBytes(context^.output, ORD(current_case^[1]), @current_case^[2]); current_case := current_case + 1 end; WriteLine(context^.output); - WriteString(context^.output, ' )') + WriteString(context^.output, " )") end; proc transpile_named_type(context: ^TranspilerContext, type_expression: ^AstTypeExpression); @@ -231,7 +231,7 @@ var current_parameter: ^^AstTypeExpression; parameter_count: Word; begin - WriteString(context^.output, 'PROCEDURE('); + WriteString(context^.output, "PROCEDURE("); current_parameter := type_expression^.parameters; while current_parameter^ <> nil do @@ -240,7 +240,7 @@ begin current_parameter := current_parameter + 1; if current_parameter^ <> nil then - WriteString(context^.output, ', ') + WriteString(context^.output, ", ") end end; WriteChar(context^.output, ')') @@ -272,10 +272,10 @@ proc transpile_type_declaration(context: ^TranspilerContext, declaration: ^AstTy var written_bytes: Word; begin - WriteString(context^.output, ' '); + WriteString(context^.output, " "); written_bytes := WriteNBytes(context^.output, ORD(declaration^.identifier[1]), @declaration^.identifier[2]); - WriteString(context^.output, ' = '); + WriteString(context^.output, " = "); transpile_type_expression(context, declaration^.type_expression); write_semicolon(context^.output) @@ -286,7 +286,7 @@ var current_declaration: ^^AstTypedDeclaration; begin if declarations^ <> nil then - WriteString(context^.output, 'TYPE'); + WriteString(context^.output, "TYPE"); WriteLine(context^.output); current_declaration := declarations; @@ -303,10 +303,10 @@ proc transpile_variable_declaration(context: ^TranspilerContext, declaration: ^A var written_bytes: Word; begin - WriteString(context^.output, ' '); + WriteString(context^.output, " "); written_bytes := WriteNBytes(context^.output, ORD(declaration^.variable_name[1]), @declaration^.variable_name[2]); - WriteString(context^.output, ': '); + WriteString(context^.output, ": "); transpile_type_expression(context, declaration^.variable_type); write_semicolon(context^.output) @@ -317,7 +317,7 @@ var current_declaration: ^^AstVariableDeclaration; begin if declarations^ <> nil then - WriteString(context^.output, 'VAR'); + WriteString(context^.output, "VAR"); WriteLine(context^.output); current_declaration := declarations; @@ -338,7 +338,7 @@ var parameter_index: Word; current_parameter: ^AstTypedDeclaration; begin - WriteString(context^.output, 'PROCEDURE '); + WriteString(context^.output, "PROCEDURE "); written_bytes := WriteNBytes(context^.output, ORD(declaration^.name[1]), @declaration^.name[2]); WriteChar(context^.output, '('); @@ -347,22 +347,22 @@ begin while parameter_index < declaration^.parameter_count do written_bytes := WriteNBytes(context^.output, ORD(current_parameter^.identifier[1]), @current_parameter^.identifier[2]); - WriteString(context^.output, ': '); + WriteString(context^.output, ": "); transpile_type_expression(context, current_parameter^.type_expression); parameter_index := parameter_index + 1u; current_parameter := current_parameter + 1; if parameter_index <> declaration^.parameter_count then - WriteString(context^.output, '; ') + WriteString(context^.output, "; ") end end; - WriteString(context^.output, ')'); + WriteString(context^.output, ")"); (* Check for the return type and write it. *) if declaration^.return_type <> nil then - WriteString(context^.output, ': '); + WriteString(context^.output, ": "); transpile_type_expression(context, declaration^.return_type) end; write_semicolon(context^.output) @@ -388,10 +388,10 @@ begin | AstBinaryOperator.not_equals: WriteChar(context^.output, '#') | AstBinaryOperator.less: WriteChar(context^.output, '<') | AstBinaryOperator.greater: WriteChar(context^.output, '>') - | AstBinaryOperator.less_equal: WriteString(context^.output, '<=') - | AstBinaryOperator.greater_equal: WriteString(context^.output, '>=') - | AstBinaryOperator.disjunction: WriteString(context^.output, 'OR') - | AstBinaryOperatorConjunction: WriteString(context^.output, 'AND') + | AstBinaryOperator.less_equal: WriteString(context^.output, "<=") + | AstBinaryOperator.greater_equal: WriteString(context^.output, ">=") + | AstBinaryOperator.disjunction: WriteString(context^.output, "OR") + | AstBinaryOperatorConjunction: WriteString(context^.output, "AND") end end; @@ -414,13 +414,13 @@ begin WriteString(context^.output, literal^.string) end; if literal^.kind = AstLiteralKind.null then - WriteString(context^.output, 'NIL') + WriteString(context^.output, "NIL") end; if (literal^.kind = AstLiteralKind.boolean) & literal^.boolean then - WriteString(context^.output, 'TRUE') + WriteString(context^.output, "TRUE") end; if (literal^.kind = AstLiteralKind.boolean) & (literal^.boolean = false) then - WriteString(context^.output, 'FALSE') + WriteString(context^.output, "FALSE") end end; if expression^.kind = astExpressionKindIdentifier then @@ -466,7 +466,7 @@ begin current_argument := current_argument + 1; while argument_index < expression^.argument_count do - WriteString(context^.output, ', '); + WriteString(context^.output, ", "); transpile_expression(context, current_argument^); @@ -480,44 +480,44 @@ end; proc transpile_if_statement(context: ^TranspilerContext, statement: ^AstStatement); begin - WriteString(context^.output, 'IF '); + WriteString(context^.output, "IF "); transpile_expression(context, statement^.if_condition); - WriteString(context^.output, ' THEN'); + WriteString(context^.output, " THEN"); WriteLine(context^.output); context^.indentation := context^.indentation + 1u; transpile_compound_statement(context, statement^.if_branch); context^.indentation := context^.indentation - 1u; indent(context); - WriteString(context^.output, 'END') + WriteString(context^.output, "END") end; proc transpile_while_statement(context: ^TranspilerContext, statement: ^AstStatement); begin - WriteString(context^.output, 'WHILE '); + WriteString(context^.output, "WHILE "); transpile_expression(context, statement^.while_condition); - WriteString(context^.output, ' DO'); + WriteString(context^.output, " DO"); WriteLine(context^.output); context^.indentation := context^.indentation + 1u; transpile_compound_statement(context, statement^.while_body); context^.indentation := context^.indentation - 1u; indent(context); - WriteString(context^.output, 'END') + WriteString(context^.output, "END") end; proc transpile_assignment_statement(context: ^TranspilerContext, statement: ^AstStatement); begin transpile_expression(context, statement^.assignee); - WriteString(context^.output, ' := '); + WriteString(context^.output, " := "); transpile_expression(context, statement^.assignment) end; proc transpile_return_statement(context: ^TranspilerContext, statement: ^AstStatement); begin - WriteString(context^.output, 'RETURN '); + WriteString(context^.output, "RETURN "); transpile_expression(context, statement^.returned) end; @@ -567,7 +567,7 @@ end; proc transpile_statement_part(context: ^TranspilerContext, compound: AstCompoundStatement); begin if compound.count > 0 then - WriteString(context^.output, 'BEGIN'); + WriteString(context^.output, "BEGIN"); WriteLine(context^.output); context^.indentation := context^.indentation + 1u; @@ -586,7 +586,7 @@ begin transpile_variable_part(context, declaration^.variables, false); transpile_statement_part(context, declaration^.statements); - WriteString(context^.output, 'END '); + WriteString(context^.output, "END "); written_bytes := WriteNBytes(context^.output, ORD(declaration^.name[1]), @declaration^.name[2]); write_semicolon(context^.output) diff --git a/source/cctype.elna b/source/cctype.elna new file mode 100644 index 0000000..a538c96 --- /dev/null +++ b/source/cctype.elna @@ -0,0 +1,11 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module; + +proc isdigit(c: Int ) -> Int; extern; +proc isalnum(c: Int) -> Int; extern; +proc isalpha(c: Int) -> Int; extern; +proc isspace(c: Int) -> Int; extern; + +end. diff --git a/source/cstdio.elna b/source/cstdio.elna new file mode 100644 index 0000000..a9352e7 --- /dev/null +++ b/source/cstdio.elna @@ -0,0 +1,23 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module; + +type + FILE* = record end; + +proc fopen(pathname: ^Char, mode: ^Char) -> ^FILE; extern; +proc fclose(stream: ^FILE) -> Int; extern; +proc fseek(stream: ^FILE, off: Int, whence: Int) -> Int; extern; +proc rewind(stream: ^FILE); extern; +proc ftell(stream: ^FILE) -> Int; extern; +proc fflush(stream: ^FILE) -> Int; extern; + +proc fread(ptr: Pointer, size: Word, nmemb: Word, stream: ^FILE) -> Word; extern; + +proc perror(s: ^Char); extern; + +proc puts(s: ^Char) -> Int; extern; +proc putchar(c: Int) -> Int; extern; + +end. diff --git a/source/cstdlib.elna b/source/cstdlib.elna new file mode 100644 index 0000000..e5369f2 --- /dev/null +++ b/source/cstdlib.elna @@ -0,0 +1,13 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module; + +proc malloc(size: Word) -> Pointer; extern; +proc free(ptr: Pointer); extern; +proc calloc(nmemb: Word, size: Word) -> Pointer; extern; +proc realloc(ptr: Pointer, size: Word) -> Pointer; extern; + +proc exit(code: Int) -> !; extern; + +end. diff --git a/source/cstring.elna b/source/cstring.elna new file mode 100644 index 0000000..903697c --- /dev/null +++ b/source/cstring.elna @@ -0,0 +1,13 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module; + +proc memset(ptr: ^Char, c: Int, n: Int) -> ^Char; extern; +proc strcmp(s1: ^Char, s2: ^Char) -> Int; extern; +proc strncmp(s1: ^Char, s2: ^Char, n: Word) -> Int; extern; +proc strncpy(dst: ^Char, src: ^Char, dsize: Word) -> ^Char; extern; +proc strcpy(dst: ^Char, src: ^Char) -> ^Char; extern; +proc strlen(ptr: ^Char) -> Word; extern; + +end. diff --git a/source/main.elna b/source/main.elna index 0f3d001..c7542b7 100644 --- a/source/main.elna +++ b/source/main.elna @@ -3,7 +3,7 @@ obtain one at https://mozilla.org/MPL/2.0/. *) program; -import Common, Lexer; +import cstdlib, cstring, cstdio, cctype, Common, Lexer; const SEEK_SET* := 0; @@ -127,30 +127,8 @@ type External procedures. *) -proc fopen(pathname: ^Char, mode: ^Char) -> ^FILE; extern; -proc fclose(stream: ^FILE) -> Int; extern; -proc fseek(stream: ^FILE, off: Int, whence: Int) -> Int; extern; -proc rewind(stream: ^FILE); extern; -proc ftell(stream: ^FILE) -> Int; extern; -proc fread(ptr: Pointer, size: Word, nmemb: Word, stream: ^FILE) -> Word; extern; proc write(fd: Int, buf: Pointer, Word: Int) -> Int; extern; -proc malloc(size: Word) -> Pointer; extern; -proc free(ptr: Pointer); extern; -proc calloc(nmemb: Word, size: Word) -> Pointer; extern; -proc realloc(ptr: Pointer, size: Word) -> Pointer; extern; - -proc memset(ptr: ^Char, c: Int, n: Int) -> ^Char; extern; - -proc strcmp(s1: ^Char, s2: ^Char) -> Int; extern; -proc strncmp(s1: ^Char, s2: ^Char, n: Word) -> Int; extern; -proc strncpy(dst: ^Char, src: ^Char, dsize: Word) -> ^Char; extern; -proc strcpy(dst: ^Char, src: ^Char) -> ^Char; extern; -proc strlen(ptr: ^Char) -> Word; extern; - -proc perror(s: ^Char); extern; -proc exit(code: Int) -> !; extern; - (* Standard procedures. *) @@ -161,12 +139,12 @@ end; proc write_s(value: String); begin - write(0, cast(value.ptr: Pointer), cast(value.length: Int)) + write(1, cast(value.ptr: Pointer), cast(value.length: Int)) end; proc write_z(value: ^Char); begin - write(0, cast(value: Pointer), cast(strlen(value): Int)) + write(1, cast(value: Pointer), cast(strlen(value): Int)) end; proc write_b(value: Bool); @@ -180,7 +158,8 @@ end; proc write_c(value: Char); begin - write(0, cast(@value: Pointer), 1) + putchar(cast(value: Int)); + fflush(nil) end; proc write_i(value: Int); @@ -212,22 +191,6 @@ begin write_i(cast(value: Int)) end; -proc is_digit(c: Char) -> Bool; - return cast(c: Int) >= cast('0': Int) & cast(c: Int) <= cast('9': Int) -end; - -proc is_alpha(c: Char) -> Bool; - return cast(c: Int) >= cast('A': Int) & cast(c: Int) <= cast('z': Int) -end; - -proc is_alnum(c: Char) -> Bool; - return is_digit(c) or is_alpha(c) -end; - -proc is_space(c: Char) -> Bool; - return c = ' ' or c = '\n' or c = '\t' -end; - proc substring(string: String, start: Word, count: Word) -> String; return String(string.ptr + start, count) end; @@ -412,7 +375,7 @@ proc lexer_spaces(source_code: ^SourceCode); var current: Char; begin - while ~source_code_empty(source_code) & is_space(source_code_head(source_code^)) do + while ~source_code_empty(source_code) & isspace(cast(source_code_head(source_code^): Int)) <> 0 do current := source_code_head(source_code^); if current = '\n' then @@ -424,7 +387,7 @@ end; (* Checker whether the character is allowed in an identificator. *) proc lexer_is_ident(char: Char) -> Bool; - return is_alnum(char) or char = '_' + return isalnum(cast(char: Int)) <> 0 or char = '_' end; proc lexer_identifier(source_code: ^SourceCode, token_content: ^StringBuffer); @@ -511,7 +474,7 @@ proc lexer_number(source_code: ^SourceCode, token_content: ^Int); begin token_content^ := 0; - while ~source_code_empty(source_code) & is_digit(source_code_head(source_code^)) do + while ~source_code_empty(source_code) & isdigit(cast(source_code_head(source_code^): Int)) <> 0 do token_content^ := token_content^ * 10 + (cast(source_code_head(source_code^): Int) - cast('0': Int)); source_code_advance(source_code) @@ -607,7 +570,7 @@ begin first_char := source_code_head(source_code); - if is_alpha(first_char) or first_char = '_' then + if isalpha(cast(first_char: Int)) <> 0 or first_char = '_' then lexer_identifier(@source_code, token_buffer); current_token := lexer_categorize(string_buffer_clear(token_buffer)) elsif first_char = '#' then @@ -616,7 +579,7 @@ begin current_token.kind := TokenKind.trait; current_token.value.string := string_dup(string_buffer_clear(token_buffer)) - elsif is_digit(first_char) then + elsif isdigit(cast(first_char: Int)) <> 0 then lexer_number(@source_code, @current_token.value.int_value); if source_code_expect(@source_code, 'u') then