Compare commits

..

No commits in common. "master" and "develop" have entirely different histories.

43 changed files with 50 additions and 1171 deletions

124
.gitignore vendored
View file

@ -9,6 +9,7 @@ picoc
build/* build/*
archives/ archives/
CMakeLists.txt
picoc.plist picoc.plist
picoc.config picoc.config
picoc.creator picoc.creator
@ -20,125 +21,4 @@ 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

View file

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View file

@ -1,7 +0,0 @@
<?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>

View file

@ -1,8 +0,0 @@
<?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>

View file

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

View file

@ -1,7 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="picoc md5.c" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="md5.c - &quot;test&quot;" 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>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -1,47 +0,0 @@
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)

View file

@ -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 stats.c \ variable.c clibrary.c platform.c include.c debug.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 stats.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 | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
@echo "" @echo ""
@echo "Everything:" @echo "Everything:"
@cat $(SRCS) *.h */*.h | wc @cat $(SRCS) *.h */*.h | wc
@ -53,7 +53,6 @@ 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

View file

@ -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, &IsExtern, &IsVolatile); TypeParse(&Parser, &ParsedType, &Identifier, &IsStatic);
HeapFree(Tokens); HeapFree(Tokens);
} }
``` ```

2
c-tests/.gitignore vendored
View file

@ -1,2 +0,0 @@
*
!*.*

View file

@ -1,7 +0,0 @@
int a, b;
int main(void) {
a = 1 + 2;
b = a + 3;
return 0;
}

View file

@ -1,73 +0,0 @@
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;
}

View file

@ -1,18 +0,0 @@
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++;
}

View file

@ -1,9 +0,0 @@
#include "extern.h"
int a;
int main(void) {
a = 1;
decrement();
return a + b;
}

View file

@ -1,4 +0,0 @@
extern int a;
extern long b;
//void decrement();

View file

@ -1,8 +0,0 @@
#include "extern.h"
long b = 1;
void decrement() {
a--;
b--;
}

View file

@ -1,17 +0,0 @@
#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;
}

View file

@ -1,202 +0,0 @@
/*
** 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);
}

View file

@ -1,12 +0,0 @@
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);
}

View file

@ -1,10 +0,0 @@
int main(void)
{
int j = 999;
for (int i = 0; i < 4; i++) {
j = i - 3;
}
return j;
}

View file

@ -1,175 +0,0 @@
/*
* 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;
}

View file

@ -1,19 +0,0 @@
int a;
#pragma test1
int b;
_Pragma( "test2" )
int main(void) {
a = 0;
#pragma test3
b = 1;
_Pragma("test4")
return a;
}

View file

@ -1,5 +0,0 @@
int a = 1;
int b = 2;
int c = a + b;
printf("%d\n", c);

View file

@ -1,27 +0,0 @@
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;
}

View file

@ -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, NULL, NULL); TypeParse(&Parser, &ReturnType, &Identifier, 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);

View file

@ -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_FULLFSYNC #ifdef F_FULLSYNC
/* 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,13 +331,11 @@ 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)
@ -560,7 +558,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);"},

View file

@ -1,7 +1,6 @@
/* 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 */
@ -1444,9 +1443,6 @@ 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)) {
@ -1469,7 +1465,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
char *CastIdentifier; char *CastIdentifier;
struct Value *CastTypeValue; struct Value *CastTypeValue;
TypeParse(Parser, &CastType, &CastIdentifier, NULL, NULL, NULL); TypeParse(Parser, &CastType, &CastIdentifier, NULL);
if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket) if (LexGetToken(Parser, &LexValue, true) != TokenCloseBracket)
ProgramFail(Parser, "brackets not closed"); ProgramFail(Parser, "brackets not closed");
@ -1668,7 +1664,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
PrefixState = false; PrefixState = false;
ParserCopy(Parser, &PreState); ParserCopy(Parser, &PreState);
TypeParse(Parser, &Typ, &Identifier, NULL, NULL, NULL); TypeParse(Parser, &Typ, &Identifier, 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;
@ -1892,7 +1888,7 @@ void ExpressionParseFunctionCall(struct ParseState *Parser,
Parser->ScopeID = OldScopeID; Parser->ScopeID = OldScopeID;
if (ParseStatement(&FuncParser, true, false) != ParseResultOk) if (ParseStatement(&FuncParser, true) != ParseResultOk)
ProgramFail(&FuncParser, "function body expected"); ProgramFail(&FuncParser, "function body expected");
if (RunIt) { if (RunIt) {

View file

@ -174,11 +174,7 @@ 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 */
@ -512,9 +508,6 @@ 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 */
@ -554,7 +547,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 DoNotConsumeTrailingSemicolon); int CheckTrailingSemicolon);
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);
@ -578,11 +571,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 *IsExtern, int *IsVolatile); int *IsStatic);
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, int *IsExtern, int *IsVolatile); char **Identifier, int *IsStatic);
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
View file

@ -93,11 +93,7 @@ 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}
}; };
@ -852,7 +848,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 <= TokenConstType); assert(Token >= TokenNone && Token <= TokenEndOfFunction);
return Token; return Token;
} }

72
parse.c
View file

@ -1,7 +1,6 @@
/* 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);
@ -12,7 +11,6 @@ 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);
@ -49,11 +47,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, false); Result = ParseStatement(Parser, CheckTrailingSemicolon);
Parser->Mode = OldMode; Parser->Mode = OldMode;
return (enum ParseResult)Result; return (enum ParseResult)Result;
} else } else
return ParseStatement(Parser, CheckTrailingSemicolon, false); return ParseStatement(Parser, CheckTrailingSemicolon);
} }
/* count the number of parameters to a function or macro */ /* count the number of parameters to a function or macro */
@ -122,7 +120,7 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser,
break; break;
} else { } else {
/* add a parameter */ /* add a parameter */
TypeParse(&ParamParser, &ParamType, &ParamIdentifier, NULL, NULL, NULL); TypeParse(&ParamParser, &ParamType, &ParamIdentifier, 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--;
@ -339,8 +337,6 @@ 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;
@ -348,7 +344,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, &IsExtern, &IsVolatile); TypeParseFront(Parser, &BasicType, &IsStatic);
do { do {
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier); TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
if ((Token != TokenVoidType && Token != TokenStructType && if ((Token != TokenVoidType && Token != TokenStructType &&
@ -362,8 +358,7 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
{ {
ParseFunctionDefinition(Parser, Typ, Identifier); ParseFunctionDefinition(Parser, Typ, Identifier);
return false; return false;
} else if (!IsExtern) { } else {
/* 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");
@ -454,14 +449,6 @@ 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)
{ {
@ -495,18 +482,8 @@ void ParseFor(struct ParseState *Parser)
if (LexGetToken(Parser, NULL, true) != TokenOpenBracket) if (LexGetToken(Parser, NULL, true) != TokenOpenBracket)
ProgramFail(Parser, "'(' expected"); ProgramFail(Parser, "'(' expected");
if (LexGetToken(Parser, NULL, false) != TokenSemicolon) { if (ParseStatement(Parser, true) != ParseResultOk)
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)
@ -519,10 +496,6 @@ 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");
@ -538,11 +511,7 @@ void ParseFor(struct ParseState *Parser)
while (Condition && Parser->Mode == RunModeRun) { while (Condition && Parser->Mode == RunModeRun) {
ParserCopyPos(Parser, &PreIncrement); ParserCopyPos(Parser, &PreIncrement);
ParseStatement(Parser, false, false); ParseStatement(Parser, 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)
@ -552,7 +521,7 @@ void ParseFor(struct ParseState *Parser)
if (Condition) { if (Condition) {
ParserCopyPos(Parser, &PreStatement); ParserCopyPos(Parser, &PreStatement);
ParseStatement(Parser, true, false); ParseStatement(Parser, true);
if (Parser->Mode == RunModeContinue) if (Parser->Mode == RunModeContinue)
Parser->Mode = RunModeRun; Parser->Mode = RunModeRun;
@ -581,12 +550,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, false) == ParseResultOk) { while (ParseStatement(Parser, true) == 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, false) == ParseResultOk) { while (ParseStatement(Parser, true) == ParseResultOk) {
} }
} }
@ -606,7 +575,7 @@ void ParseTypedef(struct ParseState *Parser)
struct ValueType **TypPtr; struct ValueType **TypPtr;
struct Value InitValue; struct Value InitValue;
TypeParse(Parser, &Typ, &TypeName, NULL, NULL, NULL); TypeParse(Parser, &Typ, &TypeName, NULL);
if (Parser->Mode == RunModeRun) { if (Parser->Mode == RunModeRun) {
TypPtr = &Typ; TypPtr = &Typ;
@ -618,7 +587,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 DoNotConsumeTrailingSemicolon) int CheckTrailingSemicolon)
{ {
int Condition; int Condition;
enum LexToken Token; enum LexToken Token;
@ -638,8 +607,6 @@ 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;
@ -728,7 +695,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, false) != ParseResultOk) if (ParseStatement(Parser, true) != ParseResultOk)
ProgramFail(Parser, "statement expected"); ProgramFail(Parser, "statement expected");
if (Parser->Mode == RunModeContinue) if (Parser->Mode == RunModeContinue)
Parser->Mode = PreMode; Parser->Mode = PreMode;
@ -767,8 +734,6 @@ 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;
@ -883,18 +848,13 @@ 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, !DoNotConsumeTrailingSemicolon) != TokenSemicolon) if (LexGetToken(Parser, NULL, true) != TokenSemicolon)
ProgramFail(Parser, "';' expected"); ProgramFail(Parser, "';' expected");
} }
@ -934,7 +894,7 @@ void PicocParse(Picoc *pc, const char *FileName, const char *Source,
EnableDebugger); EnableDebugger);
do { do {
Ok = ParseStatement(&Parser, true, false); Ok = ParseStatement(&Parser, true);
} while (Ok == ParseResultOk); } while (Ok == ParseResultOk);
if (Ok == ParseResultError) if (Ok == ParseResultError)
@ -957,7 +917,7 @@ void PicocParseInteractiveNoStartPrompt(Picoc *pc, int EnableDebugger)
do { do {
LexInteractiveStatementPrompt(pc); LexInteractiveStatementPrompt(pc);
Ok = ParseStatement(&Parser, true, false); Ok = ParseStatement(&Parser, true);
LexInteractiveCompleted(pc, &Parser); LexInteractiveCompleted(pc, &Parser);
} while (Ok == ParseResultOk); } while (Ok == ParseResultOk);

18
picoc.c
View file

@ -10,21 +10,18 @@
/* 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 (32*1024*1024) #define PICOC_STACK_SIZE (128000*4)
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;
@ -33,7 +30,6 @@ 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");
@ -51,13 +47,6 @@ 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) {
@ -77,11 +66,6 @@ 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

View file

@ -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 (32) /* maximum number of parameters to a function */ #define PARAMETER_MAX (16) /* 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
View file

@ -1,153 +0,0 @@
//
// 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
View file

@ -1,26 +0,0 @@
//
// 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
View file

@ -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, NULL, NULL); TypeParse(Parser, &MemberType, &MemberIdentifier, NULL);
if (MemberType == NULL || MemberIdentifier == NULL) if (MemberType == NULL || MemberIdentifier == NULL)
ProgramFail(Parser, "invalid type in struct"); ProgramFail(Parser, "invalid type in struct");
@ -393,12 +393,10 @@ 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 *IsExtern, int *IsVolatile) int *IsStatic)
{ {
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;
@ -406,49 +404,23 @@ 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, NULL, false); enum LexToken FollowToken = LexGetToken(Parser, &LexerValue, false);
Unsigned = (Token == TokenUnsignedType); Unsigned = (Token == TokenUnsignedType);
if (FollowToken != TokenIntType && FollowToken != TokenLongType && if (FollowToken != TokenIntType && FollowToken != TokenLongType &&
@ -464,14 +436,6 @@ 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;
@ -577,7 +541,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, NULL, NULL); TypeParse(Parser, Typ, Identifier, NULL);
if (LexGetToken(Parser, NULL, true) != TokenCloseBracket) if (LexGetToken(Parser, NULL, true) != TokenCloseBracket)
ProgramFail(Parser, "')' expected"); ProgramFail(Parser, "')' expected");
break; break;
@ -613,11 +577,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, int *IsExtern, int *IsVolatile) char **Identifier, int *IsStatic)
{ {
struct ValueType *BasicType; struct ValueType *BasicType;
TypeParseFront(Parser, &BasicType, IsStatic, IsExtern, IsVolatile); TypeParseFront(Parser, &BasicType, IsStatic);
TypeParseIdentPart(Parser, BasicType, Typ, Identifier); TypeParseIdentPart(Parser, BasicType, Typ, Identifier);
} }

View file

@ -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 (2048) #define MAX_TMP_COPY_BUF (256)
/* initialize the variable system */ /* initialize the variable system */