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/*
|
build/*
|
||||||
archives/
|
archives/
|
||||||
|
|
||||||
CMakeLists.txt
|
|
||||||
picoc.plist
|
picoc.plist
|
||||||
picoc.config
|
picoc.config
|
||||||
picoc.creator
|
picoc.creator
|
||||||
|
@ -21,4 +20,125 @@ tests/fred.txt
|
||||||
analysis.txt
|
analysis.txt
|
||||||
gmon.out
|
gmon.out
|
||||||
tests/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
|
TARGET = picoc
|
||||||
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c \
|
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 \
|
platform/platform_unix.c platform/library_unix.c \
|
||||||
cstdlib/stdio.c cstdlib/math.c cstdlib/string.c cstdlib/stdlib.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 \
|
cstdlib/time.c cstdlib/errno.c cstdlib/ctype.c cstdlib/stdbool.c \
|
||||||
|
@ -34,7 +34,7 @@ clean:
|
||||||
|
|
||||||
count:
|
count:
|
||||||
@echo "Core:"
|
@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 ""
|
||||||
@echo "Everything:"
|
@echo "Everything:"
|
||||||
@cat $(SRCS) *.h */*.h | wc
|
@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
|
platform.o: platform.c picoc.h interpreter.h platform.h
|
||||||
include.o: include.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
|
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/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
|
platform/library_unix.o: platform/library_unix.c interpreter.h platform.h
|
||||||
cstdlib/stdio.o: cstdlib/stdio.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 */
|
/* define an example structure */
|
||||||
Tokens = LexAnalyse(IntrinsicName, StructDefinition, strlen(StructDefinition), NULL);
|
Tokens = LexAnalyse(IntrinsicName, StructDefinition, strlen(StructDefinition), NULL);
|
||||||
LexInitParser(&Parser, StructDefinition, Tokens, IntrinsicName, true, false);
|
LexInitParser(&Parser, StructDefinition, Tokens, IntrinsicName, true, false);
|
||||||
TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic);
|
TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic, &IsExtern, &IsVolatile);
|
||||||
HeapFree(Tokens);
|
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);
|
strlen((char*)FuncList[Count].Prototype), NULL);
|
||||||
LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens,
|
LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens,
|
||||||
IntrinsicName, true, false);
|
IntrinsicName, true, false);
|
||||||
TypeParse(&Parser, &ReturnType, &Identifier, NULL);
|
TypeParse(&Parser, &ReturnType, &Identifier, NULL, NULL, NULL);
|
||||||
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
|
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier);
|
||||||
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
|
NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func;
|
||||||
HeapFreeMem(pc, Tokens);
|
HeapFreeMem(pc, Tokens);
|
||||||
|
|
|
@ -100,7 +100,7 @@ void UnistdFchdir(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
void UnistdFdatasync(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdFdatasync(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
#ifdef F_FULLSYNC
|
#ifdef F_FULLFSYNC
|
||||||
/* Mac OS X equivalent */
|
/* Mac OS X equivalent */
|
||||||
ReturnValue->Val->Integer = fcntl(Param[0]->Val->Integer, F_FULLFSYNC);
|
ReturnValue->Val->Integer = fcntl(Param[0]->Val->Integer, F_FULLFSYNC);
|
||||||
#else
|
#else
|
||||||
|
@ -331,11 +331,13 @@ void UnistdRmdir(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
ReturnValue->Val->Integer = rmdir(Param[0]->Val->Pointer);
|
ReturnValue->Val->Integer = rmdir(Param[0]->Val->Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void UnistdSbrk(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdSbrk(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
ReturnValue->Val->Pointer = sbrk(Param[0]->Val->Integer);
|
ReturnValue->Val->Pointer = sbrk(Param[0]->Val->Integer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void UnistdSetgid(struct ParseState *Parser, struct Value *ReturnValue,
|
void UnistdSetgid(struct ParseState *Parser, struct Value *ReturnValue,
|
||||||
struct Value **Param, int NumArgs)
|
struct Value **Param, int NumArgs)
|
||||||
|
@ -558,7 +560,7 @@ struct LibraryFunction UnistdFunctions[] =
|
||||||
{UnistdRead, "ssize_t read(int, void*, size_t);"},
|
{UnistdRead, "ssize_t read(int, void*, size_t);"},
|
||||||
{UnistdReadlink, "int readlink(char*, char*, size_t);"},
|
{UnistdReadlink, "int readlink(char*, char*, size_t);"},
|
||||||
{UnistdRmdir, "int rmdir(char*);"},
|
{UnistdRmdir, "int rmdir(char*);"},
|
||||||
{UnistdSbrk, "void *sbrk(intptr_t);"},
|
/* {UnistdSbrk, "void *sbrk(intptr_t);"}, */
|
||||||
{UnistdSetgid, "int setgid(gid_t);"},
|
{UnistdSetgid, "int setgid(gid_t);"},
|
||||||
{UnistdSetpgid, "int setpgid(pid_t, pid_t);"},
|
{UnistdSetpgid, "int setpgid(pid_t, pid_t);"},
|
||||||
{UnistdSetpgrp, "pid_t setpgrp(void);"},
|
{UnistdSetpgrp, "pid_t setpgrp(void);"},
|
||||||
|
|
10
expression.c
10
expression.c
|
@ -1,6 +1,7 @@
|
||||||
/* picoc expression evaluator - a stack-based expression evaluation system
|
/* picoc expression evaluator - a stack-based expression evaluation system
|
||||||
* which handles operator precedence */
|
* which handles operator precedence */
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "stats.h"
|
||||||
|
|
||||||
|
|
||||||
/* whether evaluation is left to right for a given precedence level */
|
/* 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);
|
ParserCopy(&PreState, Parser);
|
||||||
Token = LexGetToken(Parser, &LexValue, true);
|
Token = LexGetToken(Parser, &LexValue, true);
|
||||||
|
|
||||||
|
stats_log_expression(Token, Parser);
|
||||||
|
|
||||||
if ((((int)Token > TokenComma && (int)Token <= (int)TokenOpenBracket) ||
|
if ((((int)Token > TokenComma && (int)Token <= (int)TokenOpenBracket) ||
|
||||||
(Token == TokenCloseBracket && BracketPrecedence != 0)) &&
|
(Token == TokenCloseBracket && BracketPrecedence != 0)) &&
|
||||||
(Token != TokenColon || TernaryDepth > 0)) {
|
(Token != TokenColon || TernaryDepth > 0)) {
|
||||||
|
@ -1465,7 +1469,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
char *CastIdentifier;
|
char *CastIdentifier;
|
||||||
struct Value *CastTypeValue;
|
struct Value *CastTypeValue;
|
||||||
|
|
||||||
TypeParse(Parser, &CastType, &CastIdentifier, NULL);
|
TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL, NULL);
|
||||||
if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket)
|
if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket)
|
||||||
ProgramFail(Parser, "brackets not closed");
|
ProgramFail(Parser, "brackets not closed");
|
||||||
|
|
||||||
|
@ -1664,7 +1668,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||||
|
|
||||||
PrefixState = false;
|
PrefixState = false;
|
||||||
ParserCopy(Parser, &PreState);
|
ParserCopy(Parser, &PreState);
|
||||||
TypeParse(Parser, &Typ, &Identifier, NULL);
|
TypeParse(Parser, &Typ, &Identifier, NULL, NULL, NULL);
|
||||||
TypeValue = VariableAllocValueFromType(Parser->pc, Parser,
|
TypeValue = VariableAllocValueFromType(Parser->pc, Parser,
|
||||||
&Parser->pc->TypeType, false, NULL, false);
|
&Parser->pc->TypeType, false, NULL, false);
|
||||||
TypeValue->Val->Typ = Typ;
|
TypeValue->Val->Typ = Typ;
|
||||||
|
@ -1888,7 +1892,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser,
|
||||||
|
|
||||||
Parser->ScopeID = OldScopeID;
|
Parser->ScopeID = OldScopeID;
|
||||||
|
|
||||||
if (ParseStatement(&FuncParser, true) != ParseResultOk)
|
if (ParseStatement(&FuncParser, true, false) != ParseResultOk)
|
||||||
ProgramFail(&FuncParser, "function body expected");
|
ProgramFail(&FuncParser, "function body expected");
|
||||||
|
|
||||||
if (RunIt) {
|
if (RunIt) {
|
||||||
|
|
|
@ -174,7 +174,11 @@ enum LexToken {
|
||||||
/* 0x5c */ TokenEOF,
|
/* 0x5c */ TokenEOF,
|
||||||
TokenEndOfLine,
|
TokenEndOfLine,
|
||||||
TokenEndOfFunction,
|
TokenEndOfFunction,
|
||||||
TokenBackSlash
|
TokenBackSlash,
|
||||||
|
TokenVolatileType,
|
||||||
|
TokenHashPragma,
|
||||||
|
TokenUnderscorePragma,
|
||||||
|
TokenConstType
|
||||||
};
|
};
|
||||||
|
|
||||||
/* used in dynamic memory allocation */
|
/* used in dynamic memory allocation */
|
||||||
|
@ -508,6 +512,9 @@ struct Picoc_Struct {
|
||||||
struct Table StringTable;
|
struct Table StringTable;
|
||||||
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
|
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
|
||||||
char *StrEmpty;
|
char *StrEmpty;
|
||||||
|
|
||||||
|
/* stats */
|
||||||
|
int CollectStats;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* table.c */
|
/* table.c */
|
||||||
|
@ -547,7 +554,7 @@ extern void LexInteractiveStatementPrompt(Picoc *pc);
|
||||||
* void PicocParseInteractive(); */
|
* void PicocParseInteractive(); */
|
||||||
extern void PicocParseInteractiveNoStartPrompt(Picoc *pc, int EnableDebugger);
|
extern void PicocParseInteractiveNoStartPrompt(Picoc *pc, int EnableDebugger);
|
||||||
extern enum ParseResult ParseStatement(struct ParseState *Parser,
|
extern enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
int CheckTrailingSemicolon);
|
int CheckTrailingSemicolon, int DoNotConsumeTrailingSemicolon);
|
||||||
extern struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
extern struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
||||||
struct ValueType *ReturnType, char *Identifier);
|
struct ValueType *ReturnType, char *Identifier);
|
||||||
extern void ParseCleanup(Picoc *pc);
|
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 TypeStackSizeValue(struct Value *Val);
|
||||||
extern int TypeLastAccessibleOffset(Picoc *pc, struct Value *Val);
|
extern int TypeLastAccessibleOffset(Picoc *pc, struct Value *Val);
|
||||||
extern int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
extern int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
int *IsStatic);
|
int *IsStatic, int *IsExtern, int *IsVolatile);
|
||||||
extern void TypeParseIdentPart(struct ParseState *Parser,
|
extern void TypeParseIdentPart(struct ParseState *Parser,
|
||||||
struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
|
struct ValueType *BasicTyp, struct ValueType **Typ, char **Identifier);
|
||||||
extern void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
|
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,
|
extern struct ValueType *TypeGetMatching(Picoc *pc, struct ParseState *Parser,
|
||||||
struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates);
|
struct ValueType *ParentType, enum BaseType Base, int ArraySize, const char *Identifier, int AllowDuplicates);
|
||||||
extern struct ValueType *TypeCreateOpaqueStruct(Picoc *pc, struct ParseState *Parser,
|
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},
|
{"union", TokenUnionType},
|
||||||
{"unsigned", TokenUnsignedType},
|
{"unsigned", TokenUnsignedType},
|
||||||
{"void", TokenVoidType},
|
{"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
|
#ifdef DEBUG_LEXER
|
||||||
printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos);
|
printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos);
|
||||||
#endif
|
#endif
|
||||||
assert(Token >= TokenNone && Token <= TokenEndOfFunction);
|
assert(Token >= TokenNone && Token <= TokenConstType);
|
||||||
return Token;
|
return Token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
72
parse.c
72
parse.c
|
@ -1,6 +1,7 @@
|
||||||
/* picoc parser - parses source and executes statements */
|
/* picoc parser - parses source and executes statements */
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "stats.h"
|
||||||
|
|
||||||
static enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser,
|
static enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser,
|
||||||
int Condition, int CheckTrailingSemicolon);
|
int Condition, int CheckTrailingSemicolon);
|
||||||
|
@ -11,6 +12,7 @@ static void ParseDeclarationAssignment(struct ParseState *Parser,
|
||||||
struct Value *NewVariable, int DoAssignment);
|
struct Value *NewVariable, int DoAssignment);
|
||||||
static int ParseDeclaration(struct ParseState *Parser, enum LexToken Token);
|
static int ParseDeclaration(struct ParseState *Parser, enum LexToken Token);
|
||||||
static void ParseMacroDefinition(struct ParseState *Parser);
|
static void ParseMacroDefinition(struct ParseState *Parser);
|
||||||
|
static void ParsePragma(struct ParseState *Parser);
|
||||||
static void ParseFor(struct ParseState *Parser);
|
static void ParseFor(struct ParseState *Parser);
|
||||||
static enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace,
|
static enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace,
|
||||||
int Condition);
|
int Condition);
|
||||||
|
@ -47,11 +49,11 @@ enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser,
|
||||||
enum RunMode OldMode = Parser->Mode;
|
enum RunMode OldMode = Parser->Mode;
|
||||||
int Result;
|
int Result;
|
||||||
Parser->Mode = RunModeSkip;
|
Parser->Mode = RunModeSkip;
|
||||||
Result = ParseStatement(Parser, CheckTrailingSemicolon);
|
Result = ParseStatement(Parser, CheckTrailingSemicolon, false);
|
||||||
Parser->Mode = OldMode;
|
Parser->Mode = OldMode;
|
||||||
return (enum ParseResult)Result;
|
return (enum ParseResult)Result;
|
||||||
} else
|
} else
|
||||||
return ParseStatement(Parser, CheckTrailingSemicolon);
|
return ParseStatement(Parser, CheckTrailingSemicolon, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count the number of parameters to a function or macro */
|
/* count the number of parameters to a function or macro */
|
||||||
|
@ -120,7 +122,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* add a parameter */
|
/* add a parameter */
|
||||||
TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL);
|
TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL, NULL);
|
||||||
if (ParamType->Base == TypeVoid) {
|
if (ParamType->Base == TypeVoid) {
|
||||||
/* this isn't a real parameter at all - delete it */
|
/* this isn't a real parameter at all - delete it */
|
||||||
//ParamCount--;
|
//ParamCount--;
|
||||||
|
@ -337,6 +339,8 @@ void ParseDeclarationAssignment(struct ParseState *Parser,
|
||||||
int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
||||||
{
|
{
|
||||||
int IsStatic = false;
|
int IsStatic = false;
|
||||||
|
int IsExtern = false;
|
||||||
|
int IsVolatile = false;
|
||||||
int FirstVisit = false;
|
int FirstVisit = false;
|
||||||
char *Identifier;
|
char *Identifier;
|
||||||
struct ValueType *BasicType;
|
struct ValueType *BasicType;
|
||||||
|
@ -344,7 +348,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
||||||
struct Value *NewVariable = NULL;
|
struct Value *NewVariable = NULL;
|
||||||
Picoc *pc = Parser->pc;
|
Picoc *pc = Parser->pc;
|
||||||
|
|
||||||
TypeParseFront(Parser, &BasicType, &IsStatic);
|
TypeParseFront(Parser, &BasicType, &IsStatic, &IsExtern, &IsVolatile);
|
||||||
do {
|
do {
|
||||||
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
|
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
|
||||||
if ((Token != TokenVoidType && Token != TokenStructType &&
|
if ((Token != TokenVoidType && Token != TokenStructType &&
|
||||||
|
@ -358,7 +362,8 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
||||||
{
|
{
|
||||||
ParseFunctionDefinition(Parser, Typ, Identifier);
|
ParseFunctionDefinition(Parser, Typ, Identifier);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else if (!IsExtern) {
|
||||||
|
/* extern means declaration rather than definition, so ignore */
|
||||||
if (Typ == &pc->VoidType && Identifier != pc->StrEmpty)
|
if (Typ == &pc->VoidType && Identifier != pc->StrEmpty)
|
||||||
ProgramFail(Parser, "can't define a void variable");
|
ProgramFail(Parser, "can't define a void variable");
|
||||||
|
|
||||||
|
@ -449,6 +454,14 @@ void ParseMacroDefinition(struct ParseState *Parser)
|
||||||
ProgramFail(Parser, "'%s' is already defined", MacroNameStr);
|
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 */
|
/* copy the entire parser state */
|
||||||
void ParserCopy(struct ParseState *To, struct ParseState *From)
|
void ParserCopy(struct ParseState *To, struct ParseState *From)
|
||||||
{
|
{
|
||||||
|
@ -482,8 +495,18 @@ void ParseFor(struct ParseState *Parser)
|
||||||
if (LexGetToken(Parser, NULL, true) != TokenOpenBracket)
|
if (LexGetToken(Parser, NULL, true) != TokenOpenBracket)
|
||||||
ProgramFail(Parser, "'(' expected");
|
ProgramFail(Parser, "'(' expected");
|
||||||
|
|
||||||
if (ParseStatement(Parser, true) != ParseResultOk)
|
if (LexGetToken(Parser, NULL, false) != TokenSemicolon) {
|
||||||
|
if (ParseStatement(Parser, false, true) != ParseResultOk)
|
||||||
ProgramFail(Parser, "statement expected");
|
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);
|
ParserCopyPos(&PreConditional, Parser);
|
||||||
if (LexGetToken(Parser, NULL, false) == TokenSemicolon)
|
if (LexGetToken(Parser, NULL, false) == TokenSemicolon)
|
||||||
|
@ -496,6 +519,10 @@ void ParseFor(struct ParseState *Parser)
|
||||||
|
|
||||||
ParserCopyPos(&PreIncrement, Parser);
|
ParserCopyPos(&PreIncrement, Parser);
|
||||||
ParseStatementMaybeRun(Parser, false, false);
|
ParseStatementMaybeRun(Parser, false, false);
|
||||||
|
while (LexGetToken(Parser, NULL, false) == TokenComma) {
|
||||||
|
LexGetToken(Parser, NULL, true);
|
||||||
|
ParseStatementMaybeRun(Parser, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
|
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
|
||||||
ProgramFail(Parser, "')' expected");
|
ProgramFail(Parser, "')' expected");
|
||||||
|
@ -511,7 +538,11 @@ void ParseFor(struct ParseState *Parser)
|
||||||
|
|
||||||
while (Condition && Parser->Mode == RunModeRun) {
|
while (Condition && Parser->Mode == RunModeRun) {
|
||||||
ParserCopyPos(Parser, &PreIncrement);
|
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);
|
ParserCopyPos(Parser, &PreConditional);
|
||||||
if (LexGetToken(Parser, NULL, false) == TokenSemicolon)
|
if (LexGetToken(Parser, NULL, false) == TokenSemicolon)
|
||||||
|
@ -521,7 +552,7 @@ void ParseFor(struct ParseState *Parser)
|
||||||
|
|
||||||
if (Condition) {
|
if (Condition) {
|
||||||
ParserCopyPos(Parser, &PreStatement);
|
ParserCopyPos(Parser, &PreStatement);
|
||||||
ParseStatement(Parser, true);
|
ParseStatement(Parser, true, false);
|
||||||
|
|
||||||
if (Parser->Mode == RunModeContinue)
|
if (Parser->Mode == RunModeContinue)
|
||||||
Parser->Mode = RunModeRun;
|
Parser->Mode = RunModeRun;
|
||||||
|
@ -550,12 +581,12 @@ enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace,
|
||||||
/* condition failed - skip this block instead */
|
/* condition failed - skip this block instead */
|
||||||
enum RunMode OldMode = Parser->Mode;
|
enum RunMode OldMode = Parser->Mode;
|
||||||
Parser->Mode = RunModeSkip;
|
Parser->Mode = RunModeSkip;
|
||||||
while (ParseStatement(Parser, true) == ParseResultOk) {
|
while (ParseStatement(Parser, true, false) == ParseResultOk) {
|
||||||
}
|
}
|
||||||
Parser->Mode = OldMode;
|
Parser->Mode = OldMode;
|
||||||
} else {
|
} else {
|
||||||
/* just run it in its current mode */
|
/* 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 ValueType **TypPtr;
|
||||||
struct Value InitValue;
|
struct Value InitValue;
|
||||||
|
|
||||||
TypeParse(Parser, &Typ, &TypeName, NULL);
|
TypeParse(Parser, &Typ, &TypeName, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (Parser->Mode == RunModeRun) {
|
if (Parser->Mode == RunModeRun) {
|
||||||
TypPtr = &Typ;
|
TypPtr = &Typ;
|
||||||
|
@ -587,7 +618,7 @@ void ParseTypedef(struct ParseState *Parser)
|
||||||
|
|
||||||
/* parse a statement */
|
/* parse a statement */
|
||||||
enum ParseResult ParseStatement(struct ParseState *Parser,
|
enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
int CheckTrailingSemicolon)
|
int CheckTrailingSemicolon, int DoNotConsumeTrailingSemicolon)
|
||||||
{
|
{
|
||||||
int Condition;
|
int Condition;
|
||||||
enum LexToken Token;
|
enum LexToken Token;
|
||||||
|
@ -607,6 +638,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
ParserCopy(&PreState, Parser);
|
ParserCopy(&PreState, Parser);
|
||||||
Token = LexGetToken(Parser, &LexerValue, true);
|
Token = LexGetToken(Parser, &LexerValue, true);
|
||||||
|
|
||||||
|
stats_log_statement(Token, Parser);
|
||||||
|
|
||||||
switch (Token) {
|
switch (Token) {
|
||||||
case TokenEOF:
|
case TokenEOF:
|
||||||
return ParseResultEOF;
|
return ParseResultEOF;
|
||||||
|
@ -695,7 +728,7 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
ParserCopyPos(&PreStatement, Parser);
|
ParserCopyPos(&PreStatement, Parser);
|
||||||
do {
|
do {
|
||||||
ParserCopyPos(Parser, &PreStatement);
|
ParserCopyPos(Parser, &PreStatement);
|
||||||
if (ParseStatement(Parser, true) != ParseResultOk)
|
if (ParseStatement(Parser, true, false) != ParseResultOk)
|
||||||
ProgramFail(Parser, "statement expected");
|
ProgramFail(Parser, "statement expected");
|
||||||
if (Parser->Mode == RunModeContinue)
|
if (Parser->Mode == RunModeContinue)
|
||||||
Parser->Mode = PreMode;
|
Parser->Mode = PreMode;
|
||||||
|
@ -734,6 +767,8 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
case TokenAutoType:
|
case TokenAutoType:
|
||||||
case TokenRegisterType:
|
case TokenRegisterType:
|
||||||
case TokenExternType:
|
case TokenExternType:
|
||||||
|
case TokenVolatileType:
|
||||||
|
case TokenConstType:
|
||||||
*Parser = PreState;
|
*Parser = PreState;
|
||||||
CheckTrailingSemicolon = ParseDeclaration(Parser, Token);
|
CheckTrailingSemicolon = ParseDeclaration(Parser, Token);
|
||||||
break;
|
break;
|
||||||
|
@ -848,13 +883,18 @@ enum ParseResult ParseStatement(struct ParseState *Parser,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TokenHashPragma:
|
||||||
|
case TokenUnderscorePragma:
|
||||||
|
ParsePragma(Parser);
|
||||||
|
CheckTrailingSemicolon = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*Parser = PreState;
|
*Parser = PreState;
|
||||||
return ParseResultError;
|
return ParseResultError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckTrailingSemicolon) {
|
if (CheckTrailingSemicolon) {
|
||||||
if (LexGetToken(Parser, NULL, true) != TokenSemicolon)
|
if (LexGetToken(Parser, NULL, !DoNotConsumeTrailingSemicolon) != TokenSemicolon)
|
||||||
ProgramFail(Parser, "';' expected");
|
ProgramFail(Parser, "';' expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,7 +934,7 @@ void PicocParse(Picoc *pc, const char *FileName, const char *Source,
|
||||||
EnableDebugger);
|
EnableDebugger);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Ok = ParseStatement(&Parser, true);
|
Ok = ParseStatement(&Parser, true, false);
|
||||||
} while (Ok == ParseResultOk);
|
} while (Ok == ParseResultOk);
|
||||||
|
|
||||||
if (Ok == ParseResultError)
|
if (Ok == ParseResultError)
|
||||||
|
@ -917,7 +957,7 @@ void PicocParseInteractiveNoStartPrompt(Picoc *pc, int EnableDebugger)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
LexInteractiveStatementPrompt(pc);
|
LexInteractiveStatementPrompt(pc);
|
||||||
Ok = ParseStatement(&Parser, true);
|
Ok = ParseStatement(&Parser, true, false);
|
||||||
LexInteractiveCompleted(pc, &Parser);
|
LexInteractiveCompleted(pc, &Parser);
|
||||||
|
|
||||||
} while (Ok == ParseResultOk);
|
} 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
|
/* include only picoc.h here - should be able to use it with only the
|
||||||
external interfaces, no internals from interpreter.h */
|
external interfaces, no internals from interpreter.h */
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
|
#include "stats.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(UNIX_HOST) || defined(WIN32)
|
#if defined(UNIX_HOST) || defined(WIN32)
|
||||||
#include "LICENSE.h"
|
#include "LICENSE.h"
|
||||||
|
|
||||||
/* Override via STACKSIZE environment variable */
|
/* 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 main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ParamCount = 1;
|
int ParamCount = 1;
|
||||||
int DontRunMain = false;
|
int DontRunMain = false;
|
||||||
|
int CollectStats = false;
|
||||||
|
int StatsType = 0;
|
||||||
int StackSize = getenv("STACKSIZE") ? atoi(getenv("STACKSIZE")) : PICOC_STACK_SIZE;
|
int StackSize = getenv("STACKSIZE") ? atoi(getenv("STACKSIZE")) : PICOC_STACK_SIZE;
|
||||||
Picoc pc;
|
Picoc pc;
|
||||||
|
|
||||||
|
@ -30,6 +33,7 @@ int main(int argc, char **argv)
|
||||||
"Format:\n\n"
|
"Format:\n\n"
|
||||||
"> picoc <file1.c>... [- <arg1>...] : run a program, calls main() as the entry point\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 -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 -i : interactive mode, Ctrl+d to exit\n"
|
||||||
"> picoc -c : copyright info\n"
|
"> picoc -c : copyright info\n"
|
||||||
"> picoc -h : this help message\n");
|
"> picoc -h : this help message\n");
|
||||||
|
@ -47,6 +51,13 @@ int main(int argc, char **argv)
|
||||||
DontRunMain = true;
|
DontRunMain = true;
|
||||||
PicocIncludeAllSystemHeaders(&pc);
|
PicocIncludeAllSystemHeaders(&pc);
|
||||||
ParamCount++;
|
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) {
|
if (argc > ParamCount && strcmp(argv[ParamCount], "-i") == 0) {
|
||||||
|
@ -66,6 +77,11 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
PicocCleanup(&pc);
|
PicocCleanup(&pc);
|
||||||
|
|
||||||
|
if (CollectStats) {
|
||||||
|
stats_print_tokens(StatsType == 1);
|
||||||
|
}
|
||||||
|
|
||||||
return pc.PicocExitValue;
|
return pc.PicocExitValue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
#define STRING_TABLE_SIZE (97) /* shared string table size */
|
#define STRING_TABLE_SIZE (97) /* shared string table size */
|
||||||
#define STRING_LITERAL_TABLE_SIZE (97) /* string literal table size */
|
#define STRING_LITERAL_TABLE_SIZE (97) /* string literal table size */
|
||||||
#define RESERVED_WORD_TABLE_SIZE (97) /* reserved word 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 LINEBUFFER_MAX (256) /* maximum number of characters on a line */
|
||||||
#define LOCAL_TABLE_SIZE (11) /* size of local variable table (can expand) */
|
#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) */
|
#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);
|
STRUCT_TABLE_SIZE, true);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
TypeParse(Parser, &MemberType, &MemberIdentifier, NULL);
|
TypeParse(Parser, &MemberType, &MemberIdentifier, NULL, NULL, NULL);
|
||||||
if (MemberType == NULL || MemberIdentifier == NULL)
|
if (MemberType == NULL || MemberIdentifier == NULL)
|
||||||
ProgramFail(Parser, "invalid type in struct");
|
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 */
|
/* parse a type - just the basic type */
|
||||||
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
int *IsStatic)
|
int *IsStatic, int *IsExtern, int *IsVolatile)
|
||||||
{
|
{
|
||||||
int Unsigned = false;
|
int Unsigned = false;
|
||||||
int StaticQualifier = false;
|
int StaticQualifier = false;
|
||||||
|
int ExternQualifier = false;
|
||||||
|
int VolatileQualifier = false;
|
||||||
enum LexToken Token;
|
enum LexToken Token;
|
||||||
struct ParseState Before;
|
struct ParseState Before;
|
||||||
struct Value *LexerValue;
|
struct Value *LexerValue;
|
||||||
|
@ -404,23 +406,49 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
Picoc *pc = Parser->pc;
|
Picoc *pc = Parser->pc;
|
||||||
*Typ = NULL;
|
*Typ = NULL;
|
||||||
|
|
||||||
/* ignore leading type qualifiers */
|
|
||||||
ParserCopy(&Before, Parser);
|
ParserCopy(&Before, Parser);
|
||||||
Token = LexGetToken(Parser, &LexerValue, true);
|
Token = LexGetToken(Parser, &LexerValue, true);
|
||||||
|
|
||||||
|
/* handle any leading type qualifiers/storage classes */
|
||||||
while (Token == TokenStaticType || Token == TokenAutoType ||
|
while (Token == TokenStaticType || Token == TokenAutoType ||
|
||||||
Token == TokenRegisterType || Token == TokenExternType) {
|
Token == TokenRegisterType || Token == TokenExternType ||
|
||||||
|
Token == TokenVolatileType || Token == TokenConstType) {
|
||||||
if (Token == TokenStaticType)
|
if (Token == TokenStaticType)
|
||||||
StaticQualifier = true;
|
StaticQualifier = true;
|
||||||
|
else if (Token == TokenExternType)
|
||||||
|
ExternQualifier = true;
|
||||||
|
else if (Token == TokenVolatileType)
|
||||||
|
VolatileQualifier = true;
|
||||||
|
|
||||||
Token = LexGetToken(Parser, &LexerValue, 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)
|
if (IsStatic != NULL)
|
||||||
*IsStatic = StaticQualifier;
|
*IsStatic = StaticQualifier;
|
||||||
|
if (IsExtern != NULL)
|
||||||
|
*IsExtern = ExternQualifier;
|
||||||
|
if (IsVolatile != NULL)
|
||||||
|
*IsVolatile = VolatileQualifier;
|
||||||
|
|
||||||
/* handle signed/unsigned with no trailing type */
|
/* handle signed/unsigned with no trailing type */
|
||||||
if (Token == TokenSignedType || Token == TokenUnsignedType) {
|
if (Token == TokenSignedType || Token == TokenUnsignedType) {
|
||||||
enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false);
|
enum LexToken FollowToken = LexGetToken(Parser, NULL, false);
|
||||||
Unsigned = (Token == TokenUnsignedType);
|
Unsigned = (Token == TokenUnsignedType);
|
||||||
|
|
||||||
if (FollowToken != TokenIntType && FollowToken != TokenLongType &&
|
if (FollowToken != TokenIntType && FollowToken != TokenLongType &&
|
||||||
|
@ -436,6 +464,14 @@ int TypeParseFront(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
Token = LexGetToken(Parser, &LexerValue, true);
|
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) {
|
switch (Token) {
|
||||||
case TokenIntType:
|
case TokenIntType:
|
||||||
*Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType;
|
*Typ = Unsigned ? &pc->UnsignedIntType : &pc->IntType;
|
||||||
|
@ -541,7 +577,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
|
||||||
if (*Typ != NULL)
|
if (*Typ != NULL)
|
||||||
ProgramFail(Parser, "bad type declaration");
|
ProgramFail(Parser, "bad type declaration");
|
||||||
|
|
||||||
TypeParse(Parser, Typ, Identifier, NULL);
|
TypeParse(Parser, Typ, Identifier, NULL, NULL, NULL);
|
||||||
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
|
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
|
||||||
ProgramFail(Parser, "')' expected");
|
ProgramFail(Parser, "')' expected");
|
||||||
break;
|
break;
|
||||||
|
@ -577,11 +613,11 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp,
|
||||||
|
|
||||||
/* parse a type - a complete declaration including identifier */
|
/* parse a type - a complete declaration including identifier */
|
||||||
void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
|
void TypeParse(struct ParseState *Parser, struct ValueType **Typ,
|
||||||
char **Identifier, int *IsStatic)
|
char **Identifier, int *IsStatic, int *IsExtern, int *IsVolatile)
|
||||||
{
|
{
|
||||||
struct ValueType *BasicType;
|
struct ValueType *BasicType;
|
||||||
|
|
||||||
TypeParseFront(Parser, &BasicType, IsStatic);
|
TypeParseFront(Parser, &BasicType, IsStatic, IsExtern, IsVolatile);
|
||||||
TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
|
TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
/* maximum size of a value to temporarily copy while we create a variable */
|
/* 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 */
|
/* initialize the variable system */
|
||||||
|
|
Loading…
Reference in a new issue