Compare commits
27 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4da276b88f | ||
![]() |
29ebc3114b | ||
![]() |
31b08382db | ||
![]() |
97030639f1 | ||
![]() |
9d2327b8be | ||
![]() |
7b43483f68 | ||
![]() |
3979f563aa | ||
![]() |
d04337125e | ||
![]() |
875a635648 | ||
![]() |
5261facbd7 | ||
![]() |
62969cb0ee | ||
![]() |
9fd31b6d37 | ||
![]() |
b403e76600 | ||
![]() |
9abf00e2d3 | ||
![]() |
a96902717c | ||
![]() |
2597008035 | ||
![]() |
45d85111f0 | ||
![]() |
409f520b61 | ||
![]() |
72dff522b3 | ||
![]() |
4d3a9715ae | ||
![]() |
d57c0044b5 | ||
![]() |
a97d94fa3d | ||
![]() |
bb3c5ef926 | ||
![]() |
2e35505e26 | ||
![]() |
345b1defbd | ||
![]() |
4930d786c8 | ||
![]() |
7008ce7f9e |
124
.gitignore
vendored
124
.gitignore
vendored
|
@ -9,7 +9,6 @@ picoc
|
|||
build/*
|
||||
archives/
|
||||
|
||||
CMakeLists.txt
|
||||
picoc.plist
|
||||
picoc.config
|
||||
picoc.creator
|
||||
|
@ -21,4 +20,125 @@ tests/fred.txt
|
|||
analysis.txt
|
||||
gmon.out
|
||||
tests/gmon.out
|
||||
.idea/
|
||||
|
||||
# Created by https://www.gitignore.io/api/macos,clion
|
||||
# Edit at https://www.gitignore.io/?templates=macos,clion
|
||||
|
||||
|
||||
### CLion ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### CLion Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# End of https://www.gitignore.io/api/macos,clion
|
||||
|
|
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
7
.idea/misc.xml
Normal file
7
.idea/misc.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/picoc.iml" filepath="$PROJECT_DIR$/.idea/picoc.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
2
.idea/picoc.iml
Normal file
2
.idea/picoc.iml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
7
.idea/runConfigurations/picoc.xml
Normal file
7
.idea/runConfigurations/picoc.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/picoc_basic_c.xml
Normal file
7
.idea/runConfigurations/picoc_basic_c.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc basic.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="basic.c" REDIRECT_INPUT="false" WORKING_DIR="file://$ProjectFileDir$/c-tests" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/picoc_complete_c.xml
Normal file
7
.idea/runConfigurations/picoc_complete_c.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc complete.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="complete.c" REDIRECT_INPUT="false" WORKING_DIR="file://$ProjectFileDir$/c-tests" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/picoc_expressions_c.xml
Normal file
7
.idea/runConfigurations/picoc_expressions_c.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc expressions.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="expressions.c" REDIRECT_INPUT="false" WORKING_DIR="file://$ProjectFileDir$/c-tests" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/picoc_factorial_c.xml
Normal file
7
.idea/runConfigurations/picoc_factorial_c.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc factorial.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="factorial.c - 5" REDIRECT_INPUT="false" WORKING_DIR="file://$ProjectFileDir$/c-tests" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/picoc_loop_c.xml
Normal file
7
.idea/runConfigurations/picoc_loop_c.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc loop.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="loop.c" REDIRECT_INPUT="false" WORKING_DIR="file://$ProjectFileDir$/c-tests" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/picoc_md5_c.xml
Normal file
7
.idea/runConfigurations/picoc_md5_c.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="picoc md5.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="md5.c - "test"" REDIRECT_INPUT="false" WORKING_DIR="file://$ProjectFileDir$/c-tests" PASS_PARENT_ENVS_2="true" PROJECT_NAME="picoc" TARGET_NAME="picoc" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="picoc" RUN_TARGET_NAME="picoc">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
47
CMakeLists.txt
Normal file
47
CMakeLists.txt
Normal file
|
@ -0,0 +1,47 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
project(picoc C)
|
||||
|
||||
execute_process(COMMAND git show-ref --abbrev=8 --head --hash head OUTPUT_VARIABLE hash OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND git describe --abbrev=0 --tags OUTPUT_VARIABLE tag OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
message("${tag} ${hash}")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_COMPILER gcc)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic")
|
||||
set(CMAKE_REQUIRED_LIBRARIES m readline)
|
||||
add_definitions(-DUNIX_HOST -DVER="${hash}" -DTAG="${tag}")
|
||||
#add_definitions(-DDEBUG_EXPRESSIONS)
|
||||
|
||||
include_directories(.)
|
||||
|
||||
add_executable(picoc
|
||||
cstdlib/ctype.c
|
||||
cstdlib/errno.c
|
||||
cstdlib/math.c
|
||||
cstdlib/stdbool.c
|
||||
cstdlib/stdio.c
|
||||
cstdlib/stdlib.c
|
||||
cstdlib/string.c
|
||||
cstdlib/time.c
|
||||
cstdlib/unistd.c
|
||||
platform/library_unix.c
|
||||
platform/platform_unix.c
|
||||
clibrary.c
|
||||
debug.c
|
||||
expression.c
|
||||
heap.c
|
||||
include.c
|
||||
interpreter.h
|
||||
lex.c
|
||||
parse.c
|
||||
picoc.c
|
||||
picoc.h
|
||||
platform.c
|
||||
platform.h
|
||||
stats.c
|
||||
stats.h
|
||||
table.c
|
||||
type.c
|
||||
variable.c)
|
||||
|
||||
target_link_libraries(picoc -lm -lreadline)
|
5
Makefile
5
Makefile
|
@ -12,7 +12,7 @@ LIBS=-lm -lreadline
|
|||
|
||||
TARGET = picoc
|
||||
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c \
|
||||
variable.c clibrary.c platform.c include.c debug.c \
|
||||
variable.c clibrary.c platform.c include.c debug.c stats.c \
|
||||
platform/platform_unix.c platform/library_unix.c \
|
||||
cstdlib/stdio.c cstdlib/math.c cstdlib/string.c cstdlib/stdlib.c \
|
||||
cstdlib/time.c cstdlib/errno.c cstdlib/ctype.c cstdlib/stdbool.c \
|
||||
|
@ -34,7 +34,7 @@ clean:
|
|||
|
||||
count:
|
||||
@echo "Core:"
|
||||
@cat picoc.h interpreter.h picoc.c table.c lex.c parse.c expression.c platform.c heap.c type.c variable.c include.c debug.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
|
||||
@cat picoc.h interpreter.h picoc.c table.c lex.c parse.c expression.c platform.c heap.c type.c variable.c include.c debug.c stats.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
|
||||
@echo ""
|
||||
@echo "Everything:"
|
||||
@cat $(SRCS) *.h */*.h | wc
|
||||
|
@ -53,6 +53,7 @@ clibrary.o: clibrary.c picoc.h interpreter.h platform.h
|
|||
platform.o: platform.c picoc.h interpreter.h platform.h
|
||||
include.o: include.c picoc.h interpreter.h platform.h
|
||||
debug.o: debug.c interpreter.h platform.h
|
||||
stats.o: stats.c stats.h interpreter.h platform.h
|
||||
platform/platform_unix.o: platform/platform_unix.c picoc.h interpreter.h platform.h
|
||||
platform/library_unix.o: platform/library_unix.c interpreter.h platform.h
|
||||
cstdlib/stdio.o: cstdlib/stdio.c interpreter.h platform.h
|
||||
|
|
|
@ -327,7 +327,7 @@ void PlatformLibraryInit()
|
|||
/* define an example structure */
|
||||
Tokens = LexAnalyse(IntrinsicName, StructDefinition, strlen(StructDefinition), NULL);
|
||||
LexInitParser(&Parser, StructDefinition, Tokens, IntrinsicName, true, false);
|
||||
TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic);
|
||||
TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic, &IsExtern, &IsVolatile);
|
||||
HeapFree(Tokens);
|
||||
}
|
||||
```
|
||||
|
|
2
c-tests/.gitignore
vendored
Normal file
2
c-tests/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!*.*
|
7
c-tests/basic.c
Normal file
7
c-tests/basic.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
int a, b;
|
||||
|
||||
int main(void) {
|
||||
a = 1 + 2;
|
||||
b = a + 3;
|
||||
return 0;
|
||||
}
|
73
c-tests/complete.c
Normal file
73
c-tests/complete.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
typedef int int_type;
|
||||
|
||||
struct a_struct {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
union a_union {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
#pragma a_pragma
|
||||
|
||||
int a;
|
||||
unsigned long b = 0;
|
||||
int *c;
|
||||
char arr[5] = "test";
|
||||
|
||||
int dbl(int a, ...) {
|
||||
return a * 2;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
a = 1 + 2;
|
||||
b = dbl(a);
|
||||
|
||||
if (a < 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (0) {
|
||||
a++;
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
a--;
|
||||
} while (0);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
a += 2;
|
||||
}
|
||||
|
||||
lab: a = 1;
|
||||
goto lab;
|
||||
|
||||
struct a_struct s;
|
||||
struct a_struct *sp = &s;
|
||||
s.a = 1;
|
||||
sp->b = 2;
|
||||
|
||||
switch (a) {
|
||||
case 1:
|
||||
b = 1;
|
||||
break;
|
||||
case 2:
|
||||
b = 2;
|
||||
break;
|
||||
default:
|
||||
b = 0;
|
||||
}
|
||||
|
||||
a = b ? 1 : 2;
|
||||
|
||||
a += (int)10;
|
||||
|
||||
for(;;);
|
||||
|
||||
int c = a, b;
|
||||
|
||||
return 0, 1;
|
||||
}
|
18
c-tests/expressions.c
Normal file
18
c-tests/expressions.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
int b, c;
|
||||
int d[2];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int a = 1 + 2;
|
||||
b = a + 3 + 4 + 5;
|
||||
c = (a * b++ + 6 - 7) / 8;
|
||||
a += 1;
|
||||
b++;
|
||||
a = b + c;
|
||||
d[0] = 1;
|
||||
// *(d + 1) = 2;
|
||||
// return a = 1, b = 2;
|
||||
return a = 1;
|
||||
|
||||
a = b++;
|
||||
}
|
9
c-tests/extern.c
Normal file
9
c-tests/extern.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "extern.h"
|
||||
|
||||
int a;
|
||||
|
||||
int main(void) {
|
||||
a = 1;
|
||||
decrement();
|
||||
return a + b;
|
||||
}
|
4
c-tests/extern.h
Normal file
4
c-tests/extern.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
extern int a;
|
||||
extern long b;
|
||||
|
||||
//void decrement();
|
8
c-tests/extern2.c
Normal file
8
c-tests/extern2.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "extern.h"
|
||||
|
||||
long b = 1;
|
||||
|
||||
void decrement() {
|
||||
a--;
|
||||
b--;
|
||||
}
|
17
c-tests/factorial.c
Normal file
17
c-tests/factorial.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int in = atoi(argv[1]);
|
||||
int fact = 1;
|
||||
|
||||
for (int i = 1; i <= in; i++) {
|
||||
fact *= i;
|
||||
}
|
||||
|
||||
printf("%d factorial is %d", in, fact);
|
||||
|
||||
return 0;
|
||||
}
|
202
c-tests/hash.c
Normal file
202
c-tests/hash.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
** C implementation of a hash table ADT
|
||||
*/
|
||||
|
||||
//typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
|
||||
#define SUCCESS 0
|
||||
#define FAIL 1
|
||||
|
||||
|
||||
typedef struct tagEntry
|
||||
{
|
||||
char* key;
|
||||
char* value;
|
||||
} Entry;
|
||||
|
||||
|
||||
|
||||
typedef struct tagNode
|
||||
{
|
||||
Entry* entry;
|
||||
|
||||
struct tagNode* next;
|
||||
} Node;
|
||||
|
||||
|
||||
typedef struct tagHash
|
||||
{
|
||||
unsigned int table_size;
|
||||
|
||||
Node** heads;
|
||||
|
||||
} Hash;
|
||||
|
||||
|
||||
static unsigned int hash_func(char* str, unsigned int table_size)
|
||||
{
|
||||
unsigned int hash_value;
|
||||
unsigned int a = 127;
|
||||
|
||||
for (hash_value = 0; *str != 0; ++str)
|
||||
hash_value = (a*hash_value + *str) % table_size;
|
||||
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
|
||||
int HashCreate(Hash** hash, unsigned int table_size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (table_size < 1)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
* Allocate space for the Hash
|
||||
*/
|
||||
if (((*hash) = malloc(sizeof(**hash))) == NULL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
* Allocate space for the array of list heads
|
||||
*/
|
||||
if (((*hash)->heads = malloc(table_size*sizeof(*((*hash)->heads)))) == NULL)
|
||||
return FAIL;
|
||||
|
||||
/*
|
||||
* Initialize Hash info
|
||||
*/
|
||||
for (i = 0; i < table_size; ++i)
|
||||
{
|
||||
(*hash)->heads[i] = NULL;
|
||||
}
|
||||
|
||||
(*hash)->table_size = table_size;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int HashInsert(Hash* hash, Entry* entry)
|
||||
{
|
||||
unsigned int index = hash_func(entry->key, hash->table_size);
|
||||
Node* temp = hash->heads[index];
|
||||
|
||||
HashRemove(hash, entry->key);
|
||||
|
||||
if ((hash->heads[index] = malloc(sizeof(Node))) == NULL)
|
||||
return FAIL;
|
||||
|
||||
hash->heads[index]->entry = malloc(sizeof(Entry));
|
||||
hash->heads[index]->entry->key = malloc(strlen(entry->key)+1);
|
||||
hash->heads[index]->entry->value = malloc(strlen(entry->value)+1);
|
||||
strcpy(hash->heads[index]->entry->key, entry->key);
|
||||
strcpy(hash->heads[index]->entry->value, entry->value);
|
||||
|
||||
hash->heads[index]->next = temp;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Entry* HashFind(Hash* hash, char* key)
|
||||
{
|
||||
unsigned int index = hash_func(key, hash->table_size);
|
||||
Node* temp = hash->heads[index];
|
||||
|
||||
while (temp != NULL)
|
||||
{
|
||||
if (!strcmp(key, temp->entry->key))
|
||||
return temp->entry;
|
||||
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int HashRemove(Hash* hash, char* key)
|
||||
{
|
||||
unsigned int index = hash_func(key, hash->table_size);
|
||||
Node* temp1 = hash->heads[index];
|
||||
Node* temp2 = temp1;
|
||||
|
||||
while (temp1 != NULL)
|
||||
{
|
||||
if (!strcmp(key, temp1->entry->key))
|
||||
{
|
||||
if (temp1 == hash->heads[index])
|
||||
hash->heads[index] = hash->heads[index]->next;
|
||||
else
|
||||
temp2->next = temp1->next;
|
||||
|
||||
free(temp1->entry->key);
|
||||
free(temp1->entry->value);
|
||||
free(temp1->entry);
|
||||
free(temp1);
|
||||
temp1 = NULL;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
temp2 = temp1;
|
||||
temp1 = temp1->next;
|
||||
}
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
|
||||
void HashPrint(Hash* hash, void (*PrintFunc)(char*, char*))
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (hash == NULL || hash->heads == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < hash->table_size; ++i)
|
||||
{
|
||||
Node* temp = hash->heads[i];
|
||||
|
||||
while (temp != NULL)
|
||||
{
|
||||
PrintFunc(temp->entry->key, temp->entry->value);
|
||||
temp = temp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HashDestroy(Hash* hash)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (hash == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < hash->table_size; ++i)
|
||||
{
|
||||
Node* temp = hash->heads[i];
|
||||
|
||||
while (temp != NULL)
|
||||
{
|
||||
Node* temp2 = temp;
|
||||
|
||||
free(temp->entry->key);
|
||||
free(temp->entry->value);
|
||||
free(temp->entry);
|
||||
|
||||
temp = temp->next;
|
||||
|
||||
free(temp2);
|
||||
}
|
||||
}
|
||||
|
||||
free(hash->heads);
|
||||
hash->heads = NULL;
|
||||
|
||||
free(hash);
|
||||
}
|
12
c-tests/loop-comma.c
Normal file
12
c-tests/loop-comma.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
int main(void)
|
||||
{
|
||||
int i = 123;
|
||||
int j = 456;
|
||||
int k = 0;
|
||||
|
||||
for (i = 0, j = 0; i < 2; i++, j++) {
|
||||
k += 2;
|
||||
}
|
||||
|
||||
return k - (j * 2);
|
||||
}
|
10
c-tests/loop.c
Normal file
10
c-tests/loop.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
int main(void)
|
||||
{
|
||||
int j = 999;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
j = i - 3;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
175
c-tests/md5.c
Normal file
175
c-tests/md5.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Simple MD5 implementation
|
||||
*
|
||||
* Compile with: gcc -o md5 md5.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
// #include <stdint.h>
|
||||
|
||||
// Mostly ok, but not as a function return type for some reason
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned int size_t;
|
||||
|
||||
// Constants are the integer part of the sines of integers (in radians) * 2^32.
|
||||
uint32_t k[64] = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
|
||||
|
||||
// r specifies the per-round shift amounts
|
||||
uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
|
||||
|
||||
unsigned int left_rotate(uint32_t x, uint32_t c) {
|
||||
return (x << c) | (x >> (32 - c));
|
||||
}
|
||||
|
||||
void to_bytes(uint32_t val, uint8_t *bytes)
|
||||
{
|
||||
bytes[0] = (uint8_t) val;
|
||||
bytes[1] = (uint8_t) (val >> 8);
|
||||
bytes[2] = (uint8_t) (val >> 16);
|
||||
bytes[3] = (uint8_t) (val >> 24);
|
||||
}
|
||||
|
||||
unsigned int to_int32(uint8_t *bytes)
|
||||
{
|
||||
return (uint32_t) bytes[0]
|
||||
| ((uint32_t) bytes[1] << 8)
|
||||
| ((uint32_t) bytes[2] << 16)
|
||||
| ((uint32_t) bytes[3] << 24);
|
||||
}
|
||||
|
||||
void md5(uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {
|
||||
|
||||
// These vars will contain the hash
|
||||
uint32_t h0, h1, h2, h3;
|
||||
|
||||
// Message (to prepare)
|
||||
uint8_t *msg = NULL;
|
||||
|
||||
size_t new_len, offset;
|
||||
uint32_t w[16];
|
||||
uint32_t a, b, c, d, i, f, g, temp;
|
||||
|
||||
// Initialize variables - simple count in nibbles:
|
||||
h0 = 0x67452301;
|
||||
h1 = 0xefcdab89;
|
||||
h2 = 0x98badcfe;
|
||||
h3 = 0x10325476;
|
||||
|
||||
//Pre-processing:
|
||||
//append "1" bit to message
|
||||
//append "0" bits until message length in bits ≡ 448 (mod 512)
|
||||
//append length mod (2^64) to message
|
||||
|
||||
for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++);
|
||||
|
||||
msg = malloc(new_len + 8);
|
||||
memcpy(msg, initial_msg, initial_len);
|
||||
msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"
|
||||
for (offset = initial_len + 1; offset < new_len; offset++)
|
||||
msg[offset] = 0; // append "0" bits
|
||||
|
||||
// append the len in bits at the end of the buffer.
|
||||
to_bytes(initial_len*8, msg + new_len);
|
||||
// initial_len>>29 == initial_len*8>>32, but avoids overflow.
|
||||
to_bytes(initial_len>>29, msg + new_len + 4);
|
||||
|
||||
// Process the message in successive 512-bit chunks:
|
||||
//for each 512-bit chunk of message:
|
||||
for(offset=0; offset<new_len; offset += (512/8)) {
|
||||
|
||||
// break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
|
||||
for (i = 0; i < 16; i++)
|
||||
w[i] = to_int32(msg + offset + i*4);
|
||||
|
||||
// Initialize hash value for this chunk:
|
||||
a = h0;
|
||||
b = h1;
|
||||
c = h2;
|
||||
d = h3;
|
||||
|
||||
// Main loop:
|
||||
for(i = 0; i<64; i++) {
|
||||
|
||||
if (i < 16) {
|
||||
f = (b & c) | ((~b) & d);
|
||||
g = i;
|
||||
} else if (i < 32) {
|
||||
f = (d & b) | ((~d) & c);
|
||||
g = (5*i + 1) % 16;
|
||||
} else if (i < 48) {
|
||||
f = b ^ c ^ d;
|
||||
g = (3*i + 5) % 16;
|
||||
} else {
|
||||
f = c ^ (b | (~d));
|
||||
g = (7*i) % 16;
|
||||
}
|
||||
|
||||
temp = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b = b + left_rotate((a + f + k[i] + w[g]), r[i]);
|
||||
a = temp;
|
||||
|
||||
}
|
||||
|
||||
// Add this chunk's hash to result so far:
|
||||
h0 += a;
|
||||
h1 += b;
|
||||
h2 += c;
|
||||
h3 += d;
|
||||
|
||||
}
|
||||
|
||||
// cleanup
|
||||
free(msg);
|
||||
|
||||
//var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
|
||||
to_bytes(h0, digest);
|
||||
to_bytes(h1, digest + 4);
|
||||
to_bytes(h2, digest + 8);
|
||||
to_bytes(h3, digest + 12);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *msg = argv[1];
|
||||
size_t len;
|
||||
int i;
|
||||
uint8_t result[16];
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: %s 'string'\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = strlen(msg);
|
||||
|
||||
md5((uint8_t*)msg, len, result);
|
||||
|
||||
// display result
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%2.2x", result[i]);
|
||||
puts("");
|
||||
|
||||
return 0;
|
||||
}
|
19
c-tests/pragma.c
Normal file
19
c-tests/pragma.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
int a;
|
||||
|
||||
#pragma test1
|
||||
|
||||
int b;
|
||||
|
||||
_Pragma( "test2" )
|
||||
|
||||
int main(void) {
|
||||
a = 0;
|
||||
|
||||
#pragma test3
|
||||
|
||||
b = 1;
|
||||
|
||||
_Pragma("test4")
|
||||
|
||||
return a;
|
||||
}
|
5
c-tests/test.c
Normal file
5
c-tests/test.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
int a = 1;
|
||||
int b = 2;
|
||||
int c = a + b;
|
||||
|
||||
printf("%d\n", c);
|
27
c-tests/types.c
Normal file
27
c-tests/types.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
int a;
|
||||
|
||||
unsigned b;
|
||||
unsigned int c;
|
||||
|
||||
long d;
|
||||
long int e;
|
||||
unsigned long f;
|
||||
unsigned long int g;
|
||||
|
||||
short h;
|
||||
short int i;
|
||||
unsigned short j;
|
||||
unsigned short int k;
|
||||
|
||||
volatile int l;
|
||||
int volatile static m;
|
||||
|
||||
const int x;
|
||||
long const y;
|
||||
|
||||
typedef int MyInt;
|
||||
MyInt z = 1;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}
|
|
@ -46,7 +46,7 @@ void LibraryAdd(Picoc *pc, struct LibraryFunction *FuncList)
|
|||
strlen((char*)FuncList[Count].Prototype), NULL);
|
||||
LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens,
|
||||
IntrinsicName, true, false);
|
||||
TypeParse(&Parser, &ReturnType, &Identifier, NULL);
|
||||
TypeParse(&Parser, &ReturnType, &Identifier, NULL, NULL, NULL);
|
||||
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
|
||||
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
|
||||
HeapFreeMem(pc, Tokens);
|
||||
|
|
|
@ -100,7 +100,7 @@ void UnistdFchdir(struct ParseState *Parser, struct Value *ReturnValue,
|
|||
void UnistdFdatasync(struct ParseState *Parser, struct Value *ReturnValue,
|
||||
struct Value **Param, int NumArgs)
|
||||
{
|
||||
#ifdef F_FULLSYNC
|
||||
#ifdef F_FULLFSYNC
|
||||
/* Mac OS X equivalent */
|
||||
ReturnValue->Val->Integer = fcntl(Param[0]->Val->Integer, F_FULLFSYNC);
|
||||
#else
|
||||
|
@ -331,11 +331,13 @@ void UnistdRmdir(struct ParseState *Parser, struct Value *ReturnValue,
|
|||
ReturnValue->Val->Integer = rmdir(Param[0]->Val->Pointer);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void UnistdSbrk(struct ParseState *Parser, struct Value *ReturnValue,
|
||||
struct Value **Param, int NumArgs)
|
||||
{
|
||||
ReturnValue->Val->Pointer = sbrk(Param[0]->Val->Integer);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UnistdSetgid(struct ParseState *Parser, struct Value *ReturnValue,
|
||||
struct Value **Param, int NumArgs)
|
||||
|
@ -558,7 +560,7 @@ struct LibraryFunction UnistdFunctions[] =
|
|||
{UnistdRead, "ssize_t read(int, void*, size_t);"},
|
||||
{UnistdReadlink, "int readlink(char*, char*, size_t);"},
|
||||
{UnistdRmdir, "int rmdir(char*);"},
|
||||
{UnistdSbrk, "void *sbrk(intptr_t);"},
|
||||
/* {UnistdSbrk, "void *sbrk(intptr_t);"}, */
|
||||
{UnistdSetgid, "int setgid(gid_t);"},
|
||||
{UnistdSetpgid, "int setpgid(pid_t, pid_t);"},
|
||||
{UnistdSetpgrp, "pid_t setpgrp(void);"},
|
||||
|
|
10
expression.c
10
expression.c
|
@ -1,6 +1,7 @@
|
|||
/* picoc expression evaluator - a stack-based expression evaluation system
|
||||
* which handles operator precedence */
|
||||
#include "interpreter.h"
|
||||
#include "stats.h"
|
||||
|
||||
|
||||
/* whether evaluation is left to right for a given precedence level */
|
||||
|
@ -1443,6 +1444,9 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
|
||||
ParserCopy(&PreState, Parser);
|
||||
Token = LexGetToken(Parser, &LexValue, true);
|
||||
|
||||
stats_log_expression(Token, Parser);
|
||||
|
||||
if ((((int)Token > TokenComma && (int)Token <= (int)TokenOpenBracket) ||
|
||||
(Token == TokenCloseBracket && BracketPrecedence != 0)) &&
|
||||
(Token != TokenColon || TernaryDepth > 0)) {
|
||||
|
@ -1465,7 +1469,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
char *CastIdentifier;
|
||||
struct Value *CastTypeValue;
|
||||
|
||||
TypeParse(Parser, &CastType, &CastIdentifier, NULL);
|
||||
TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL, NULL);
|
||||
if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "brackets not closed");
|
||||
|
||||
|
@ -1664,7 +1668,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
|
||||
PrefixState = false;
|
||||
ParserCopy(Parser, &PreState);
|
||||
TypeParse(Parser, &Typ, &Identifier, NULL);
|
||||
TypeParse(Parser, &Typ, &Identifier, NULL, NULL, NULL);
|
||||
TypeValue = VariableAllocValueFromType(Parser->pc, Parser,
|
||||
&Parser->pc->TypeType, false, NULL, false);
|
||||
TypeValue->Val->Typ = Typ;
|
||||
|
@ -1888,7 +1892,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser,
|
|||
|
||||
Parser->ScopeID = OldScopeID;
|
||||
|
||||
if (ParseStatement(&FuncParser, true) != ParseResultOk)
|
||||
if (ParseStatement(&FuncParser, true, false) != ParseResultOk)
|
||||
ProgramFail(&FuncParser, "function body expected");
|
||||
|
||||
if (RunIt) {
|
||||
|
|
|
@ -174,7 +174,11 @@ enum LexToken {
|
|||
/* 0x5c */ TokenEOF,
|
||||
TokenEndOfLine,
|
||||
TokenEndOfFunction,
|
||||
TokenBackSlash
|
||||
TokenBackSlash,
|
||||
TokenVolatileType,
|
||||
TokenHashPragma,
|
||||
TokenUnderscorePragma,
|
||||
TokenConstType
|
||||
};
|
||||
|
||||
/* used in dynamic memory allocation */
|
||||
|
@ -508,6 +512,9 @@ struct Picoc_Struct {
|
|||
struct Table StringTable;
|
||||
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
|
||||
char *StrEmpty;
|
||||
|
||||
/* stats */
|
||||
int CollectStats;
|
||||
};
|
||||
|
||||
/* table.c */
|
||||
|
@ -547,7 +554,7 @@ extern void LexInteractiveStatementPrompt(Picoc *pc);
|
|||
* void PicocParseInteractive(); */
|
||||
extern void PicocParseInteractiveNoStartPrompt(Picoc *pc, int EnableDebugger);
|
||||
extern enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||
int CheckTrailingSemicolon);
|
||||
int CheckTrailingSemicolon, int DoNotConsumeTrailingSemicolon);
|
||||
extern struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
||||
struct ValueType *ReturnType, char *Identifier);
|
||||
extern void ParseCleanup(Picoc *pc);
|
||||
|
@ -571,11 +578,11 @@ extern int TypeSizeValue(struct Value *Val, int Compact);
|
|||
extern int TypeStackSizeValue(struct Value *Val);
|
||||
extern int TypeLastAccessibleOffset(Picoc *pc, struct Value *Val);
|
||||
extern int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||
int *IsStatic);
|
||||
int *IsStatic, int *IsExtern, int *IsVolatile);
|
||||
extern void TypeParseIdentPart(struct ParseState *Parser,
|
||||
struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
|
||||
extern void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
|
||||
char **Identifier, int *IsStatic);
|
||||
char **Identifier, int *IsStatic, int *IsExtern, int *IsVolatile);
|
||||
extern struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
|
||||
struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates);
|
||||
extern struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser,
|
||||
|
|
8
lex.c
8
lex.c
|
@ -93,7 +93,11 @@ static struct ReservedWord ReservedWords[] = {
|
|||
{"union", TokenUnionType},
|
||||
{"unsigned", TokenUnsignedType},
|
||||
{"void", TokenVoidType},
|
||||
{"while", TokenWhile}
|
||||
{"while", TokenWhile},
|
||||
{"volatile", TokenVolatileType},
|
||||
{"#pragma", TokenHashPragma},
|
||||
{"_Pragma", TokenUnderscorePragma},
|
||||
{"const", TokenConstType}
|
||||
};
|
||||
|
||||
|
||||
|
@ -848,7 +852,7 @@ enum LexToken LexGetRawToken(struct ParseState *Parser, struct Value **Value,
|
|||
#ifdef DEBUG_LEXER
|
||||
printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos);
|
||||
#endif
|
||||
assert(Token >= TokenNone && Token <= TokenEndOfFunction);
|
||||
assert(Token >= TokenNone && Token <= TokenConstType);
|
||||
return Token;
|
||||
}
|
||||
|
||||
|
|
72
parse.c
72
parse.c
|
@ -1,6 +1,7 @@
|
|||
/* picoc parser - parses source and executes statements */
|
||||
#include "picoc.h"
|
||||
#include "interpreter.h"
|
||||
#include "stats.h"
|
||||
|
||||
static enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser,
|
||||
int Condition, int CheckTrailingSemicolon);
|
||||
|
@ -11,6 +12,7 @@ static void ParseDeclarationAssignment(struct ParseState *Parser,
|
|||
struct Value *NewVariable, int DoAssignment);
|
||||
static int ParseDeclaration(struct ParseState *Parser, enum LexToken Token);
|
||||
static void ParseMacroDefinition(struct ParseState *Parser);
|
||||
static void ParsePragma(struct ParseState *Parser);
|
||||
static void ParseFor(struct ParseState *Parser);
|
||||
static enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace,
|
||||
int Condition);
|
||||
|
@ -47,11 +49,11 @@ enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser,
|
|||
enum RunMode OldMode = Parser->Mode;
|
||||
int Result;
|
||||
Parser->Mode = RunModeSkip;
|
||||
Result = ParseStatement(Parser, CheckTrailingSemicolon);
|
||||
Result = ParseStatement(Parser, CheckTrailingSemicolon, false);
|
||||
Parser->Mode = OldMode;
|
||||
return (enum ParseResult)Result;
|
||||
} else
|
||||
return ParseStatement(Parser, CheckTrailingSemicolon);
|
||||
return ParseStatement(Parser, CheckTrailingSemicolon, false);
|
||||
}
|
||||
|
||||
/* count the number of parameters to a function or macro */
|
||||
|
@ -120,7 +122,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
|||
break;
|
||||
} else {
|
||||
/* add a parameter */
|
||||
TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL);
|
||||
TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL, NULL);
|
||||
if (ParamType->Base == TypeVoid) {
|
||||
/* this isn't a real parameter at all - delete it */
|
||||
//ParamCount--;
|
||||
|
@ -337,6 +339,8 @@ void ParseDeclarationAssignment(struct ParseState *Parser,
|
|||
int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
||||
{
|
||||
int IsStatic = false;
|
||||
int IsExtern = false;
|
||||
int IsVolatile = false;
|
||||
int FirstVisit = false;
|
||||
char *Identifier;
|
||||
struct ValueType *BasicType;
|
||||
|
@ -344,7 +348,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
|||
struct Value *NewVariable = NULL;
|
||||
Picoc *pc = Parser->pc;
|
||||
|
||||
TypeParseFront(Parser, &BasicType, &IsStatic);
|
||||
TypeParseFront(Parser, &BasicType, &IsStatic, &IsExtern, &IsVolatile);
|
||||
do {
|
||||
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
|
||||
if ((Token != TokenVoidType && Token != TokenStructType &&
|
||||
|
@ -358,7 +362,8 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
|||
{
|
||||
ParseFunctionDefinition(Parser, Typ, Identifier);
|
||||
return false;
|
||||
} else {
|
||||
} else if (!IsExtern) {
|
||||
/* extern means declaration rather than definition, so ignore */
|
||||
if (Typ == &pc->VoidType && Identifier != pc->StrEmpty)
|
||||
ProgramFail(Parser, "can't define a void variable");
|
||||
|
||||
|
@ -449,6 +454,14 @@ void ParseMacroDefinition(struct ParseState *Parser)
|
|||
ProgramFail(Parser, "'%s' is already defined", MacroNameStr);
|
||||
}
|
||||
|
||||
/* parse a pragma */
|
||||
void ParsePragma(struct ParseState *Parser)
|
||||
{
|
||||
/* consume tokens until we hit the end of a line */
|
||||
/* (not ideal for _Pragma() but it'll do for now) */
|
||||
LexToEndOfMacro(Parser);
|
||||
}
|
||||
|
||||
/* copy the entire parser state */
|
||||
void ParserCopy(struct ParseState *To, struct ParseState *From)
|
||||
{
|
||||
|
@ -482,8 +495,18 @@ void ParseFor(struct ParseState *Parser)
|
|||
if (LexGetToken(Parser, NULL, true) != TokenOpenBracket)
|
||||
ProgramFail(Parser, "'(' expected");
|
||||
|
||||
if (ParseStatement(Parser, true) != ParseResultOk)
|
||||
if (LexGetToken(Parser, NULL, false) != TokenSemicolon) {
|
||||
if (ParseStatement(Parser, false, true) != ParseResultOk)
|
||||
ProgramFail(Parser, "statement expected");
|
||||
while (LexGetToken(Parser, NULL, false) == TokenComma) {
|
||||
LexGetToken(Parser, NULL, true);
|
||||
if (ParseStatement(Parser, false, true) != ParseResultOk)
|
||||
ProgramFail(Parser, "statement expected");
|
||||
}
|
||||
}
|
||||
|
||||
if (LexGetToken(Parser, NULL, true) != TokenSemicolon)
|
||||
ProgramFail(Parser, "';' expected");
|
||||
|
||||
ParserCopyPos(&PreConditional, Parser);
|
||||
if (LexGetToken(Parser, NULL, false) == TokenSemicolon)
|
||||
|
@ -496,6 +519,10 @@ void ParseFor(struct ParseState *Parser)
|
|||
|
||||
ParserCopyPos(&PreIncrement, Parser);
|
||||
ParseStatementMaybeRun(Parser, false, false);
|
||||
while (LexGetToken(Parser, NULL, false) == TokenComma) {
|
||||
LexGetToken(Parser, NULL, true);
|
||||
ParseStatementMaybeRun(Parser, false, false);
|
||||
}
|
||||
|
||||
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
|
@ -511,7 +538,11 @@ void ParseFor(struct ParseState *Parser)
|
|||
|
||||
while (Condition && Parser->Mode == RunModeRun) {
|
||||
ParserCopyPos(Parser, &PreIncrement);
|
||||
ParseStatement(Parser, false);
|
||||
ParseStatement(Parser, false, false);
|
||||
while (LexGetToken(Parser, NULL, false) == TokenComma) {
|
||||
LexGetToken(Parser, NULL, true);
|
||||
ParseStatement(Parser, false, false);
|
||||
}
|
||||
|
||||
ParserCopyPos(Parser, &PreConditional);
|
||||
if (LexGetToken(Parser, NULL, false) == TokenSemicolon)
|
||||
|
@ -521,7 +552,7 @@ void ParseFor(struct ParseState *Parser)
|
|||
|
||||
if (Condition) {
|
||||
ParserCopyPos(Parser, &PreStatement);
|
||||
ParseStatement(Parser, true);
|
||||
ParseStatement(Parser, true, false);
|
||||
|
||||
if (Parser->Mode == RunModeContinue)
|
||||
Parser->Mode = RunModeRun;
|
||||
|
@ -550,12 +581,12 @@ enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace,
|
|||
/* condition failed - skip this block instead */
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
Parser->Mode = RunModeSkip;
|
||||
while (ParseStatement(Parser, true) == ParseResultOk) {
|
||||
while (ParseStatement(Parser, true, false) == ParseResultOk) {
|
||||
}
|
||||
Parser->Mode = OldMode;
|
||||
} else {
|
||||
/* just run it in its current mode */
|
||||
while (ParseStatement(Parser, true) == ParseResultOk) {
|
||||
while (ParseStatement(Parser, true, false) == ParseResultOk) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,7 +606,7 @@ void ParseTypedef(struct ParseState *Parser)
|
|||
struct ValueType **TypPtr;
|
||||
struct Value InitValue;
|
||||
|
||||
TypeParse(Parser, &Typ, &TypeName, NULL);
|
||||
TypeParse(Parser, &Typ, &TypeName, NULL, NULL, NULL);
|
||||
|
||||
if (Parser->Mode == RunModeRun) {
|
||||
TypPtr = &Typ;
|
||||
|
@ -587,7 +618,7 @@ void ParseTypedef(struct ParseState *Parser)
|
|||
|
||||
/* parse a statement */
|
||||
enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||
int CheckTrailingSemicolon)
|
||||
int CheckTrailingSemicolon, int DoNotConsumeTrailingSemicolon)
|
||||
{
|
||||
int Condition;
|
||||
enum LexToken Token;
|
||||
|
@ -607,6 +638,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
|||
ParserCopy(&PreState, Parser);
|
||||
Token = LexGetToken(Parser, &LexerValue, true);
|
||||
|
||||
stats_log_statement(Token, Parser);
|
||||
|
||||
switch (Token) {
|
||||
case TokenEOF:
|
||||
return ParseResultEOF;
|
||||
|
@ -695,7 +728,7 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
|||
ParserCopyPos(&PreStatement, Parser);
|
||||
do {
|
||||
ParserCopyPos(Parser, &PreStatement);
|
||||
if (ParseStatement(Parser, true) != ParseResultOk)
|
||||
if (ParseStatement(Parser, true, false) != ParseResultOk)
|
||||
ProgramFail(Parser, "statement expected");
|
||||
if (Parser->Mode == RunModeContinue)
|
||||
Parser->Mode = PreMode;
|
||||
|
@ -734,6 +767,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
|||
case TokenAutoType:
|
||||
case TokenRegisterType:
|
||||
case TokenExternType:
|
||||
case TokenVolatileType:
|
||||
case TokenConstType:
|
||||
*Parser = PreState;
|
||||
CheckTrailingSemicolon = ParseDeclaration(Parser, Token);
|
||||
break;
|
||||
|
@ -848,13 +883,18 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TokenHashPragma:
|
||||
case TokenUnderscorePragma:
|
||||
ParsePragma(Parser);
|
||||
CheckTrailingSemicolon = false;
|
||||
break;
|
||||
default:
|
||||
*Parser = PreState;
|
||||
return ParseResultError;
|
||||
}
|
||||
|
||||
if (CheckTrailingSemicolon) {
|
||||
if (LexGetToken(Parser, NULL, true) != TokenSemicolon)
|
||||
if (LexGetToken(Parser, NULL, !DoNotConsumeTrailingSemicolon) != TokenSemicolon)
|
||||
ProgramFail(Parser, "';' expected");
|
||||
}
|
||||
|
||||
|
@ -894,7 +934,7 @@ void PicocParse(Picoc *pc, const char *FileName, const char *Source,
|
|||
EnableDebugger);
|
||||
|
||||
do {
|
||||
Ok = ParseStatement(&Parser, true);
|
||||
Ok = ParseStatement(&Parser, true, false);
|
||||
} while (Ok == ParseResultOk);
|
||||
|
||||
if (Ok == ParseResultError)
|
||||
|
@ -917,7 +957,7 @@ void PicocParseInteractiveNoStartPrompt(Picoc *pc, int EnableDebugger)
|
|||
|
||||
do {
|
||||
LexInteractiveStatementPrompt(pc);
|
||||
Ok = ParseStatement(&Parser, true);
|
||||
Ok = ParseStatement(&Parser, true, false);
|
||||
LexInteractiveCompleted(pc, &Parser);
|
||||
|
||||
} while (Ok == ParseResultOk);
|
||||
|
|
18
picoc.c
18
picoc.c
|
@ -10,18 +10,21 @@
|
|||
/* include only picoc.h here - should be able to use it with only the
|
||||
external interfaces, no internals from interpreter.h */
|
||||
#include "picoc.h"
|
||||
#include "stats.h"
|
||||
|
||||
|
||||
#if defined(UNIX_HOST) || defined(WIN32)
|
||||
#include "LICENSE.h"
|
||||
|
||||
/* Override via STACKSIZE environment variable */
|
||||
#define PICOC_STACK_SIZE (128000*4)
|
||||
#define PICOC_STACK_SIZE (32*1024*1024)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ParamCount = 1;
|
||||
int DontRunMain = false;
|
||||
int CollectStats = false;
|
||||
int StatsType = 0;
|
||||
int StackSize = getenv("STACKSIZE") ? atoi(getenv("STACKSIZE")) : PICOC_STACK_SIZE;
|
||||
Picoc pc;
|
||||
|
||||
|
@ -30,6 +33,7 @@ int main(int argc, char **argv)
|
|||
"Format:\n\n"
|
||||
"> picoc <file1.c>... [- <arg1>...] : run a program, calls main() as the entry point\n"
|
||||
"> picoc -s <file1.c>... [- <arg1>...] : run a script, runs the program without calling main()\n"
|
||||
"> picoc -d[type] <file1.c>... [- <arg1>...] : run a program, outputting debugging stats\n"
|
||||
"> picoc -i : interactive mode, Ctrl+d to exit\n"
|
||||
"> picoc -c : copyright info\n"
|
||||
"> picoc -h : this help message\n");
|
||||
|
@ -47,6 +51,13 @@ int main(int argc, char **argv)
|
|||
DontRunMain = true;
|
||||
PicocIncludeAllSystemHeaders(&pc);
|
||||
ParamCount++;
|
||||
} else if (strncmp(argv[ParamCount], "-d", 2) == 0) {
|
||||
if (strlen(argv[ParamCount]) > 2) {
|
||||
StatsType = atoi(&argv[ParamCount][2]);
|
||||
}
|
||||
CollectStats = true;
|
||||
pc.CollectStats = true;
|
||||
ParamCount++;
|
||||
}
|
||||
|
||||
if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0) {
|
||||
|
@ -66,6 +77,11 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
PicocCleanup(&pc);
|
||||
|
||||
if (CollectStats) {
|
||||
stats_print_tokens(StatsType == 1);
|
||||
}
|
||||
|
||||
return pc.PicocExitValue;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
#define STRING_TABLE_SIZE (97) /* shared string table size */
|
||||
#define STRING_LITERAL_TABLE_SIZE (97) /* string literal table size */
|
||||
#define RESERVED_WORD_TABLE_SIZE (97) /* reserved word table size */
|
||||
#define PARAMETER_MAX (16) /* maximum number of parameters to a function */
|
||||
#define PARAMETER_MAX (32) /* maximum number of parameters to a function */
|
||||
#define LINEBUFFER_MAX (256) /* maximum number of characters on a line */
|
||||
#define LOCAL_TABLE_SIZE (11) /* size of local variable table (can expand) */
|
||||
#define STRUCT_TABLE_SIZE (11) /* size of struct/union member table (can expand) */
|
||||
|
|
153
stats.c
Normal file
153
stats.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// Created by Russell Joyce on 12/05/2020.
|
||||
//
|
||||
|
||||
#include "stats.h"
|
||||
|
||||
const char *RunModeNames[NO_RUN_MODES] = {
|
||||
"RunModeRun",
|
||||
"RunModeSkip",
|
||||
"RunModeReturn",
|
||||
"RunModeCaseSearch",
|
||||
"RunModeBreak",
|
||||
"RunModeContinue",
|
||||
"RunModeGoto"
|
||||
};
|
||||
|
||||
struct LexTokenStat LexTokenStats[NO_TOKENS] = {
|
||||
{"TokenNone", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenComma", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenAddAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenSubtractAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenMultiplyAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDivideAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenModulusAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenShiftLeftAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenShiftRightAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenArithmeticAndAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenArithmeticOrAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenArithmeticExorAssign", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenQuestionMark", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenColon", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLogicalOr", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLogicalAnd", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenArithmeticOr", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenArithmeticExor", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenAmpersand", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenEqual", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenNotEqual", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLessThan", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenGreaterThan", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLessEqual", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenGreaterEqual", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenShiftLeft", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenShiftRight", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenPlus", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenMinus", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenAsterisk", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenSlash", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenModulus", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenIncrement", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDecrement", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenUnaryNot", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenUnaryExor", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenSizeof", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenCast", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLeftSquareBracket", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenRightSquareBracket", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDot", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenArrow", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenOpenBracket", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenCloseBracket", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenIdentifier", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenIntegerConstant", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenFPConstant", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenStringConstant", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenCharacterConstant", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenSemicolon", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenEllipsis", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLeftBrace", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenRightBrace", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenIntType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenCharType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenFloatType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDoubleType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenVoidType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenEnumType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenLongType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenSignedType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenShortType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenStaticType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenAutoType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenRegisterType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenExternType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenStructType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenUnionType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenUnsignedType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenTypedef", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenContinue", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDo", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenElse", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenFor", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenGoto", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenIf", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenWhile", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenBreak", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenSwitch", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenCase", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDefault", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenReturn", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashDefine", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashInclude", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashIf", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashIfdef", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashIfndef", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashElse", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashEndif", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenNew", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenDelete", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenOpenMacroBracket", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenEOF", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenEndOfLine", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenEndOfFunction", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenBackSlash", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenVolatileType", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenHashPragma", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenUnderscorePragma", {0, 0, 0, 0, 0, 0, 0}},
|
||||
{"TokenConstType", {0, 0, 0, 0, 0, 0, 0}}
|
||||
};
|
||||
|
||||
|
||||
void stats_log_statement(enum LexToken token, struct ParseState *parser) {
|
||||
if (parser->pc->CollectStats) {
|
||||
fprintf(stderr, "Parsing Statement %s (%d) in %s (%d) at %s:%d:%d\n", LexTokenStats[token].name, token,
|
||||
RunModeNames[parser->Mode], parser->Mode, parser->FileName, parser->Line, parser->CharacterPos);
|
||||
LexTokenStats[token].count[parser->Mode]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stats_log_expression(enum LexToken token, struct ParseState *parser) {
|
||||
if (parser->pc->CollectStats) {
|
||||
fprintf(stderr, "Parsing Expression %s (%d) in %s (%d) at %s:%d:%d\n", LexTokenStats[token].name, token,
|
||||
RunModeNames[parser->Mode], parser->Mode, parser->FileName, parser->Line, parser->CharacterPos);
|
||||
LexTokenStats[token].count[parser->Mode]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void stats_print_tokens(int all) {
|
||||
fprintf(stderr, "\n*********\nToken stats:\n");
|
||||
for (int i = 0; i < NO_RUN_MODES; i++) {
|
||||
fprintf(stderr, "***\n");
|
||||
fprintf(stderr, "%s\n", RunModeNames[i]);
|
||||
for (int j = 0; j < NO_TOKENS; j++) {
|
||||
if (all || LexTokenStats[j].count[i] > 0) {
|
||||
fprintf(stderr, "%5d %s\n", LexTokenStats[j].count[i],
|
||||
LexTokenStats[j].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "*********\n");
|
||||
}
|
26
stats.h
Normal file
26
stats.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Created by Russell Joyce on 12/05/2020.
|
||||
//
|
||||
|
||||
#ifndef PICOC_STATS_H
|
||||
#define PICOC_STATS_H
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
#define NO_RUN_MODES 7
|
||||
#define NO_TOKENS 101
|
||||
|
||||
extern const char *RunModeNames[NO_RUN_MODES];
|
||||
|
||||
struct LexTokenStat {
|
||||
const char* name;
|
||||
int count[NO_RUN_MODES];
|
||||
};
|
||||
|
||||
extern struct LexTokenStat LexTokenStats[NO_TOKENS];
|
||||
|
||||
void stats_log_statement(enum LexToken token, struct ParseState *parser);
|
||||
void stats_log_expression(enum LexToken token, struct ParseState *parser);
|
||||
void stats_print_tokens(int all);
|
||||
|
||||
#endif //PICOC_STATS_H
|
52
type.c
52
type.c
|
@ -265,7 +265,7 @@ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ,
|
|||
STRUCT_TABLE_SIZE, true);
|
||||
|
||||
do {
|
||||
TypeParse(Parser, &MemberType, &MemberIdentifier, NULL);
|
||||
TypeParse(Parser, &MemberType, &MemberIdentifier, NULL, NULL, NULL);
|
||||
if (MemberType == NULL || MemberIdentifier == NULL)
|
||||
ProgramFail(Parser, "invalid type in struct");
|
||||
|
||||
|
@ -393,10 +393,12 @@ void TypeParseEnum(struct ParseState *Parser, struct ValueType **Typ)
|
|||
|
||||
/* parse a type - just the basic type */
|
||||
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||
int *IsStatic)
|
||||
int *IsStatic, int *IsExtern, int *IsVolatile)
|
||||
{
|
||||
int Unsigned = false;
|
||||
int StaticQualifier = false;
|
||||
int ExternQualifier = false;
|
||||
int VolatileQualifier = false;
|
||||
enum LexToken Token;
|
||||
struct ParseState Before;
|
||||
struct Value *LexerValue;
|
||||
|
@ -404,23 +406,49 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
|||
Picoc *pc = Parser->pc;
|
||||
*Typ = NULL;
|
||||
|
||||
/* ignore leading type qualifiers */
|
||||
ParserCopy(&Before, Parser);
|
||||
Token = LexGetToken(Parser, &LexerValue, true);
|
||||
|
||||
/* handle any leading type qualifiers/storage classes */
|
||||
while (Token == TokenStaticType || Token == TokenAutoType ||
|
||||
Token == TokenRegisterType || Token == TokenExternType) {
|
||||
Token == TokenRegisterType || Token == TokenExternType ||
|
||||
Token == TokenVolatileType || Token == TokenConstType) {
|
||||
if (Token == TokenStaticType)
|
||||
StaticQualifier = true;
|
||||
else if (Token == TokenExternType)
|
||||
ExternQualifier = true;
|
||||
else if (Token == TokenVolatileType)
|
||||
VolatileQualifier = true;
|
||||
|
||||
Token = LexGetToken(Parser, &LexerValue, true);
|
||||
}
|
||||
|
||||
/* handle any trailing type qualifiers/storage classes */
|
||||
enum LexToken FollowToken = LexGetToken(Parser, NULL, false);
|
||||
while (FollowToken == TokenStaticType || FollowToken == TokenAutoType ||
|
||||
FollowToken == TokenRegisterType || FollowToken == TokenExternType ||
|
||||
FollowToken == TokenVolatileType || FollowToken == TokenConstType) {
|
||||
if (FollowToken == TokenStaticType)
|
||||
StaticQualifier = true;
|
||||
else if (FollowToken == TokenExternType)
|
||||
ExternQualifier = true;
|
||||
else if (FollowToken == TokenVolatileType)
|
||||
VolatileQualifier = true;
|
||||
|
||||
LexGetToken(Parser, NULL, true);
|
||||
FollowToken = LexGetToken(Parser, NULL, false);
|
||||
}
|
||||
|
||||
if (IsStatic != NULL)
|
||||
*IsStatic = StaticQualifier;
|
||||
if (IsExtern != NULL)
|
||||
*IsExtern = ExternQualifier;
|
||||
if (IsVolatile != NULL)
|
||||
*IsVolatile = VolatileQualifier;
|
||||
|
||||
/* handle signed/unsigned with no trailing type */
|
||||
if (Token == TokenSignedType || Token == TokenUnsignedType) {
|
||||
enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false);
|
||||
enum LexToken FollowToken = LexGetToken(Parser, NULL, false);
|
||||
Unsigned = (Token == TokenUnsignedType);
|
||||
|
||||
if (FollowToken != TokenIntType && FollowToken != TokenLongType &&
|
||||
|
@ -436,6 +464,14 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
|||
Token = LexGetToken(Parser, &LexerValue, true);
|
||||
}
|
||||
|
||||
/* handle long or short with trailing int by consuming and ignoring the int */
|
||||
if (Token == TokenLongType || Token == TokenShortType) {
|
||||
enum LexToken FollowToken = LexGetToken(Parser, NULL, false);
|
||||
if (FollowToken == TokenIntType) {
|
||||
LexGetToken(Parser, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
switch (Token) {
|
||||
case TokenIntType:
|
||||
*Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType;
|
||||
|
@ -541,7 +577,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
|
|||
if (*Typ != NULL)
|
||||
ProgramFail(Parser, "bad type declaration");
|
||||
|
||||
TypeParse(Parser, Typ, Identifier, NULL);
|
||||
TypeParse(Parser, Typ, Identifier, NULL, NULL, NULL);
|
||||
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
break;
|
||||
|
@ -577,11 +613,11 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
|
|||
|
||||
/* parse a type - a complete declaration including identifier */
|
||||
void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
|
||||
char **Identifier, int *IsStatic)
|
||||
char **Identifier, int *IsStatic, int *IsExtern, int *IsVolatile)
|
||||
{
|
||||
struct ValueType *BasicType;
|
||||
|
||||
TypeParseFront(Parser, &BasicType, IsStatic);
|
||||
TypeParseFront(Parser, &BasicType, IsStatic, IsExtern, IsVolatile);
|
||||
TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "interpreter.h"
|
||||
|
||||
/* maximum size of a value to temporarily copy while we create a variable */
|
||||
#define MAX_TMP_COPY_BUF (256)
|
||||
#define MAX_TMP_COPY_BUF (2048)
|
||||
|
||||
|
||||
/* initialize the variable system */
|
||||
|
|
Loading…
Reference in a new issue