Skip to content

Commit

Permalink
add 0.10.0 version files
Browse files Browse the repository at this point in the history
  • Loading branch information
amtoine committed Sep 9, 2022
1 parent 78357af commit 151cc0a
Show file tree
Hide file tree
Showing 152 changed files with 31,798 additions and 0 deletions.
674 changes: 674 additions & 0 deletions COPYING

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
INTRODUCTION

OBNC is a compiler for Niklaus Wirth's programming language Oberon. It translates Oberon modules into C code. The build command (obnc) invokes both the Oberon compiler (obnc-compile) and the host C compiler and sorts out all dependencies.

OBNC follows POSIX standard. This implies that it should compile and run on a POSIX compatible operating system.


INSTALLATION

1. Make sure you have Boehm-Demers-Weiser's garbage collector GC installed on your system. To use the basic library modules Input and XYplane you also need SDL (Simple DirectMedia Layer). On a Debian system you install these dependencies with the command

apt install libgc-dev libsdl1.2-dev

2. Compile OBNC with the command

./build

By default OBNC is built to be installed in /usr/local. If you want to use installation directory D instead, add `--prefix=D' to the build command. For other build options, run `./build -h'.

3. Optionally, run unit tests with the command

./test

4. Install OBNC with the command

./install

To undo the installation, run `./install u'. For other installation options, run `./build -h'.


COMMANDS

bin/obnc
Oberon build tool

bin/obnc-compile
Oberon-to-C compiler

bin/obnc-path
Oberon module finder

bin/obncdoc
Oberon documentation generator


DOCUMENTATION

share/doc/obnc/oberon-report.html
Oberon language reference

share/doc/obnc/obncdoc/
Basic library modules

share/man/man1/
OBNC commands


LICENSE

OBNC is released under the GNU General Public License, see file COPYING.


AUTHOR

Karl Landstrom <karl@miasap.se>
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.10.0
279 changes: 279 additions & 0 deletions bin/micb
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
#!/bin/sh

#micb - MIASAP C Builder
#
#usage: micb MODULE.c
#
#Builds an executable with MODULE.c as entry point. Imported modules are compiled or recompiled as needed. For any module M, compiler, compiler flags, link flags and link libraries specific to M can be specified by setting the variables CC, CFLAGS, LDFLAGS and LDLIBS respectively in a file named M.env.

# Copyright (C) 2017 Karl Landstrom <karl@miasap.se>
#
# This file is part of OBNC.
#
# OBNC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OBNC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OBNC. If not, see <http://www.gnu.org/licenses/>.

set -o errexit -o nounset

readonly selfDirPath="$(cd "$(dirname "$0")"; pwd -P)"
readonly micbIncludes="$selfDirPath/micb-includes"
readonly CC="${CC:-cc}"
readonly CFLAGS="${CFLAGS:-}"
readonly LDFLAGS="${LDFLAGS:-}"
readonly LDLIBS="${LDLIBS:-}"

IncludeFiles()
{
local filename="$1"

local prefix="$(dirname "$filename")/"
prefix="${prefix#./}"
"$micbIncludes" < "$filename" | while read header; do echo "$prefix$header"; done
}


MapPut()
{
local key="$1"
local value="$2"
local map="$3"

if [ -z "$map" ]; then
echo "$key$(printf '\t')$value"
else
echo "$map" | \
awk -v key="$key" -v value="$value" \
'BEGIN { FS = "\t"; keyFound = 0 }
$1 == key { print key"\t"value; keyFound = 1 }
$1 != key { print $0 }
END { if (! keyFound) { print key"\t"value } }'
fi
}


MapHas()
{
local key="$1"
local map="$2"

echo "$map" | grep -q "^$key$(printf '\t')"
}


MapAt()
{
local key="$1"
local map="$2"

echo "$map" | awk -v key="$key" 'BEGIN { FS = "\t" } $1 == key { print $2 }'
}


EnvValue()
{
local ident="$1"
local envFile="$2"

local quot="'"
local apos='"'
local value="$(awk -F "[$quot$apos=]+" -v ident="$ident" '$1 == ident { print $2 }' "$envFile")"
eval "value=\"$value\"" #expand embedded commands, like pkg-config
echo "$value"
}


Compile()
{
local cFile="$1"

local module="${cFile%.c}"
local moduleCC=
local moduleCFLAGS=
if [ -e "$module.env" ]; then
moduleCC="$(EnvValue CC "$module.env")"
moduleCFLAGS="$(EnvValue CFLAGS "$module.env")"
fi
if [ -z "$moduleCC" ]; then
moduleCC="$CC"
fi
local compileCommand="$moduleCC -c -o $module.o $CFLAGS $moduleCFLAGS $module.c"
compileCommand="$(echo "$compileCommand" | sed 's/ */ /g')"
echo "$compileCommand"
$compileCommand
}


UpdateObjectFile()
{
local sourceFile="$1"
local newestFile="$2"

local module="${sourceFile%.*}"
if [ "$sourceFile" = "$module.c" ]; then
if [ ! -e "$module.o" ] \
|| [ "$module.o" -ot "$newestFile" ] \
|| { [ -e "$module.env" ] && [ "$module.o" -ot "$module.env" ]; }; then
Compile "$sourceFile"
fi
fi
}


discoveredFiles="" #map with "filename" as key and "newest file in subgraph" as value

Traverse()
{
local filename="$1"
local nodePath="$2" #for detecting include cycles
local nodeHandler="$3"

discoveredFiles="$(MapPut "$filename" "" "$discoveredFiles")"

#traverse include files
local includeFile
local newestFileInSubgraph
local newestFile="$filename"
for includeFile in $(IncludeFiles "$filename"); do
if ! { echo "$nodePath" | grep -q -Fx "$includeFile"; }; then
if ! MapHas "$includeFile" "$discoveredFiles"; then
Traverse "$includeFile" "$nodePath\n$includeFile" "$nodeHandler"
fi
newestFileInSubgraph="$(MapAt "$includeFile" "$discoveredFiles")"
if [ "$newestFile" -ot "$newestFileInSubgraph" ]; then
newestFile="$newestFileInSubgraph"
fi
else
local cycle="$(echo "$nodePath" | tr '\n' ' ')$includeFile"
echo "$0: warning: include cycle found: $cycle" >&2
fi
done

discoveredFiles="$(MapPut "$filename" "$newestFile" "$discoveredFiles")"

"$nodeHandler" "$filename" "$newestFile"

#for a header file, also traverse the implementation file
local module="${filename%.*}"
if [ "${filename%.h}" != "$filename" ] && [ -e "$module.c" ] && ! MapHas "$module.c" "$discoveredFiles"; then
Traverse "$module.c" "$module.c" "$nodeHandler"
fi
}


NewestFile()
{
local files="$1"

local result="$(echo "$files" | head -n 1)"
for file in $files; do
if [ "$result" -ot "$file" ]; then
result="$file"
fi
done
echo "$result"
}


EnvFiles()
{
local sourceFiles="$1"

echo "$sourceFiles" \
| while read srcFile; do
envFile="${srcFile%.*}.env"
if [ -e "$envFile" ]; then
echo "$envFile"
fi
done \
| sort | uniq
}


OptionUnion()
{
local ident="$1"
local envFiles="$2"

echo "$envFiles" \
| while read envFile; do
EnvValue "$ident" "$envFile"
done \
| tr ' ' '\n' | sort | uniq | tr '\n' ' '
}


Link()
{
local objectFiles="$1"
local exeFile="$2"

local objectFileArgs="$(echo "$objectFiles" | tr '\n' ' ')"
local sourceFiles="$(echo "$discoveredFiles" | awk 'BEGIN { FS = "\t" } { print $1 }')"
local envFiles="$(EnvFiles "$sourceFiles")"
local ldflags="$(OptionUnion LDFLAGS "$envFiles")"
local ldlibs="$(OptionUnion LDLIBS "$envFiles")"

local linkCommand="$CC -o $exeFile $ldflags $LDFLAGS $objectFileArgs $ldlibs $LDLIBS"
linkCommand="$(echo "$linkCommand" | sed 's/ */ /g')"
echo "$linkCommand"
$linkCommand
}


Build()
{
local cFile="$1"

discoveredFiles=""
Traverse "$cFile" "$cFile" UpdateObjectFile

local exeFile="${cFile%.c}"
local cFiles="$(echo "$discoveredFiles" | awk 'BEGIN { FS = "\t" } $1 ~ /\.c$/ { print $1 }')"
local objectFiles="$(echo "$cFiles" | sed 's/\.c$/.o/')"
local newestObjectFile="$(NewestFile "$objectFiles")"

if [ ! -e "$exeFile" ] || [ "$exeFile" -ot "$newestObjectFile" ]; then
Link "$objectFiles" "$exeFile"
else
echo "$exeFile is up to date"
fi
}


Run()
{
local syntaxError=false

if [ "$#" = 1 ]; then
case $1 in
-*) syntaxError=true;;
*.c)
if [ -e "$1" ]; then
Build "$1"
else
echo "$0: no such file: $1" >&2
false
fi;;
*) syntaxError=true
esac
else
syntaxError=true
fi

if "$syntaxError"; then
echo "synopsis: $(basename "$0") MODULE.c" >&2
false
fi
}

Run "$@"
Loading

0 comments on commit 151cc0a

Please sign in to comment.