+++ /dev/null
-#!/bin/sh
-
-# Copyright (C) 2017, 2018, 2019 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 nounset
-
-EndsWith()
-{
- local suffix="$1"
- local target="$2"
-
- test "${target%$suffix}" != "$target"
-}
-
-readonly selfDirPath="$(cd "$(dirname "$0")"; pwd -P)"
-readonly packagePath="$(dirname "$selfDirPath")"
-
-path="$(env OBNC_IMPORT_PATH='' "$selfDirPath/obnc-path" Out | tr '\\' '/')"
-exitStatus="$?"
-expectedResult="$packagePath/lib/obnc"
-
-if [ "$exitStatus" -eq 0 ]; then
- #NOTE: In MinGW on Windows the path returned by obnc-path ends with $selfDirPath
- if ! EndsWith "$expectedResult" "$path"; then
- echo "$(basename "$0") failed: result: '$path', expected result: $expectedResult" >&2
- exit 1
- fi
-else
- echo "$(basename "$0") failed: exit status: $exitStatus" >&2
- exit 1
-fi
+++ /dev/null
-#!/usr/bin/awk -f
-
-# Copyright (C) 2017, 2018, 2019 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/>.
-
-function Indentation(line,
- result)
-{
- match(line, "^[ \t]+")
- if (RLENGTH > 0) {
- result = substr(line, RSTART, RLENGTH)
- } else {
- result = ""
- }
- return result
-}
-
-
-function MatchSyntax(line, regex,
- regex1, pos, found, matchedString, commentLevel, insideString)
-{
- #ignore comments and strings
- regex1 = "("regex")|\\(\\*|\\*\\)|\""
- match(line, regex1)
- pos = RSTART
- while (! found && (RSTART > 0)) {
- matchedString = substr(line, pos, RLENGTH)
- if ((matchedString == "(*") && ! insideString) {
- commentLevel++
- } else if ((matchedString == "*)") && ! insideString) {
- commentLevel--
- } else if ((matchedString == "\"") && (commentLevel == 0)) {
- insideString = ! insideString
- } else if ((commentLevel == 0) && ! insideString) {
- found = 1
- }
- if (! found) {
- pos += RLENGTH
- match(substr(line, pos), regex1)
- if (RSTART > 0) {
- pos += RSTART - 1
- } else {
- pos = 0
- }
- }
- }
- RSTART = pos
- return RSTART
-}
-
-
-function CommentLevelAtEndOfLine(line, currentLevel,
- regexp, matchedString)
-{
- regexp = "\\(\\*|\\*\\)|\""
- match(line, regexp)
- while (RSTART > 0) {
- matchedString = substr(line, RSTART, RLENGTH)
- line = substr(line, RSTART + RLENGTH)
- if (matchedString == "(*") {
- currentLevel++
- } else if (matchedString == "*)") {
- currentLevel--
- } else if (matchedString == "\"") {
- if (currentLevel == 0) {
- line = substr(line, index(line, "\"") + 1)
- }
- }
- match(line, regexp)
- }
- return currentLevel
-}
-
-
-function EndsInsideRecord(line,
- parts)
-{
- return MatchSyntax(line, "[^"identCharSet"]RECORD([^"identCharSet"]|$)") \
- && ! MatchSyntax(line, "[^"identCharSet"]END[ \t]*;")
-}
-
-
-function TrackQualifiers(line,
- regex, matchedString)
-{
- regex = identRegex"\\."identRegex
- MatchSyntax(line, regex)
- while (RSTART > 0) {
- matchedString = substr(line, RSTART, RLENGTH)
- line = substr(line, RSTART + RLENGTH)
- match(matchedString, identRegex)
- publicImports[substr(matchedString, 1, RLENGTH)] = ""
- MatchSyntax(line, regex)
- }
-}
-
-
-function ExportedParts(line,
- left, right)
-{
- match(line, "[=:;(]")
- if (RSTART > 0) {
- left = substr(line, 1, RSTART - 1)
- right = substr(line, RSTART)
- if ((index(left, ",") > 0) && (currentSection != "IMPORT")) {
- #exclude non-exported identifiers
- gsub(identRegex"[ \t]*,[ \t]*", "", left)
- sub("(,[ \t]*)?"identRegex"[ \t]*$", "", left)
- }
- gsub("\\*", "", left)
-
- #skip past trailing semi-colon (if any)
- MatchSyntax(right, ";")
- while (RSTART > 0) {
- left = left "" substr(right, 1, RSTART)
- right = substr(right, RSTART + RLENGTH)
- MatchSyntax(right, ";")
- }
-
- #skip to trailing comment (if any)
- match(right, "[ \t]*\\(\\*")
- if (RSTART > 0) {
- left = left "" substr(right, 1, RSTART - 1)
- right = substr(right, RSTART)
- }
-
- #delete non-exported comments
- if (MatchSyntax(left, "PROCEDURE")) {
- gsub("[ \t]*\\(\\*[^*]*\\*\\)", "", left)
- }
- sub("^[ \t]*\\(\\*([^*].*|$)", "", right)
-
- #unmark exported comments
- if (MatchSyntax(left, "PROCEDURE")) {
- gsub("\\(\\*\\*", "(*", left)
- }
- sub("^[ \t]*\\(\\*\\*", " (*", right)
-
- line = left""right
- }
- return line
-}
-
-BEGIN {
- leadingIdentCharSet = "A-Za-z"
- identCharSet = leadingIdentCharSet"0-9_"
- identRegex = "["leadingIdentCharSet"]["identCharSet"]*"
- exportedIdentRegex = identRegex"[ \t]*\\*"
- exportedIdentListRegex = "("identRegex"[ \t]*,[ \t]*)*"identRegex"[ \t]*\\*([ \t]*,[ \t]*"identRegex")*"
- split("", output)
- split("", sectionExported)
- split("", sectionHasExportedComment)
- split("", publicImports)
- recordLevel = 0
- split("", recordExported)
- split("", exportedFieldFound)
- moduleIdent = ""
- currentSection = "MODULE"
- sectionExported["MODULE"] = 1
- commentLevel = 0
- insideExportedComment = 0
- insideParamList = 0
-}
-
-(commentLevel == 0) && /^[ \t]*$/ {
- if ((currentSection == "IMPORT") || sectionExported[currentSection]) {
- sub("\n+$", "\n\n", output[currentSection])
- }
- next
-}
-
-(commentLevel == 0) && ($1 == "MODULE") {
- if (substr($2, length($2), 1) == ";") {
- moduleIdent = substr($2, 1, length($2) - 1)
- } else {
- moduleIdent = $2
- }
- line = $0
- sub(/MODULE/, "DEFINITION", line)
- commentLevel = CommentLevelAtEndOfLine(line, commentLevel)
- output[currentSection] = output[currentSection] ExportedParts(line) "\n"
- next
-}
-
-(commentLevel == 0) && ((currentSection != "PROCEDURE") && ($1 ~ "^(IMPORT|CONST|TYPE|VAR)$") || ($1 == "PROCEDURE") && ($2 ~ "^"identRegex)) {
- currentSection = $1
-}
-
-(commentLevel == 0) && (currentSection == "IMPORT") {
- commentLevel = CommentLevelAtEndOfLine($0, commentLevel)
- output[currentSection] = output[currentSection] ExportedParts($0) "\n"
- next
-}
-
-(commentLevel == 0) && (currentSection != "PROCEDURE") && ($1 ~ "^(CONST|TYPE|VAR)$") {
- if (match($2$3, "^"exportedIdentRegex)) {
- TrackQualifiers($0)
- if (EndsInsideRecord($0)) {
- recordExported[recordLevel + 1] = 1
- }
- sectionExported[$1] = 1
- }
- commentLevel = CommentLevelAtEndOfLine($0, commentLevel)
- if (EndsInsideRecord($0)) {
- recordLevel++
- }
- output[currentSection] = output[currentSection] ExportedParts($0) "\n"
- next
-}
-
-(commentLevel == 0) && (currentSection ~ "^(TYPE|VAR)$") && ($0 ~ "^[ \t]*END[ \t]*([;(]|$)") {
- if (recordExported[recordLevel]) {
- line = $0
- if (! exportedFieldFound[recordLevel]) {
- sub("^[ \t]*", " ", line)
- }
- recordExported[recordLevel] = 0
- exportedFieldFound[recordLevel] = 0
- output[currentSection] = output[currentSection] ExportedParts(line) "\n"
- }
- recordLevel--
- next
-}
-
-(commentLevel == 0) && ($0 ~ "^[ \t]*(PROCEDURE[ \t]+)?"exportedIdentListRegex) {
- TrackQualifiers($0)
- if ((recordLevel > 0) && recordExported[recordLevel]) {
- if (! exportedFieldFound[recordLevel]) {
- output[currentSection] = output[currentSection] "\n"
- exportedFieldFound[recordLevel] = 1
- }
- }
- commentLevel = CommentLevelAtEndOfLine($0, commentLevel)
- output[currentSection] = output[currentSection] ExportedParts($0)
- if (EndsInsideRecord($0)) {
- recordLevel++
- recordExported[recordLevel] = 1
- } else {
- output[currentSection] = output[currentSection] "\n"
- }
- sectionExported[currentSection] = 1
- insideParamList = ($1 == "PROCEDURE") && MatchSyntax($0, "\\(") && ! MatchSyntax($0, "\\)")
- next
-}
-
-insideParamList {
- output[currentSection] = output[currentSection] ExportedParts($0) "\n"
- insideParamList = ! MatchSyntax($0, "\\)")
- next
-}
-
-(commentLevel == 0) && (currentSection ~ "^(TYPE|VAR)$") && EndsInsideRecord($0) {
- recordLevel++
- next
-}
-
-(commentLevel == 0) && ($1 ~ "^\\(\\*\\*?") {
- commentLevel = CommentLevelAtEndOfLine($0, commentLevel)
- if (match($1, "^\\(\\*\\*")) {
- sectionHasExportedComment[currentSection] = 1
- line = $0
- sub(/\(\*\*/, "(*", line)
- if (commentLevel > 0) {
- insideExportedComment = 1
- }
- output[currentSection] = output[currentSection] line "\n"
- }
- next
-}
-
-commentLevel > 0 {
- if (insideExportedComment) {
- output[currentSection] = output[currentSection] $0 "\n"
- }
- commentLevel = CommentLevelAtEndOfLine($0, commentLevel)
- if (commentLevel == 0) {
- insideExportedComment = 0
- }
-}
-
-END {
- n = 0
- for (key in publicImports) {
- n++
- }
- if (n > 0) {
- sectionExported["IMPORT"] = 1
-
- #keep only public imports
- regex = identRegex "([ \t]*:=[ \t]*" identRegex ")?[ \t]*(,[ \t]*)?"
- left = ""
- right = output["IMPORT"]
- ##skip keyword IMPORT
- pos = MatchSyntax(right, "IMPORT")
- left = substr(right, 1, pos - 1 + RLENGTH)
- right = substr(right, pos + RLENGTH)
- ##
- pos = MatchSyntax(right, regex)
- while (pos > 0) {
- import = substr(right, pos, RLENGTH)
- split(import, importParts, "[ \t:=,]+")
- qualifier = importParts[1]
- if (qualifier in publicImports) {
- left = left substr(right, 1, pos - 1 + RLENGTH)
- } else {
- left = left substr(right, 1, pos - 1)
- }
- right = substr(right, pos + RLENGTH)
- pos = MatchSyntax(right, regex)
- }
- importList = left right
- ##fixup separators
- hasFinalBlankLine = match(importList, "\n[ \t]*\n")
- gsub(",[ \t\n]*;", ";", importList)
- gsub("\n[ \t]*\n", "\n", importList)
- if (hasFinalBlankLine) {
- importList = importList "\n"
- }
- output["IMPORT"] = importList
- }
-
- split("MODULE IMPORT CONST TYPE VAR PROCEDURE", sections)
- sectionsLen = 6
-
- hasExportedIdent = 0
- for (i = 3; i <= sectionsLen; i++) {
- if (sectionExported[sections[i]]) {
- hasExportedIdent = 1
- }
- }
- if (! hasExportedIdent) {
- sub("\n+$", "\n", output["MODULE"])
- }
-
- for (i = 1; i <= sectionsLen; i++) {
- section = sections[i]
- if (sectionExported[section]) {
- printf "%s", output[section]
- } else if (sectionHasExportedComment[section]) {
- #account for exported comment preceeding an exported procedure
- sub("^[ \t]*" section "[ \t\n]*\n", "", output[section])
- printf "%s", output[section]
- }
- }
-
- print "END " moduleIdent "."
-}
+++ /dev/null
-#!/bin/sh
-
-# Copyright (C) 2017, 2018, 2019 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
-
-echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Library Index</title>
- <link rel="stylesheet" type="text/css" href="style.css" />
- </head>
- <body>
- <p>Library Index</p>
-
- <pre>'
-
-for file in *; do
- if [ -e "$file/index.html" ]; then
- echo "Library <a href='$file/index.html'>$file</a>"
- fi
-done
-
-echo '</pre>
- </body>
-</html>'
+++ /dev/null
-#!/usr/bin/awk -f
-
-#markup definition file
-
-# Copyright (C) 2017, 2018, 2019 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/>.
-
-BEGIN {
- commentLevel = 0
-}
-
-{
- gsub(/&/, "\\&", $0)
- gsub(/</, "\\<", $0)
- gsub(/>/, "\\>", $0)
-}
-
-(commentLevel == 0) && (($1 == "DEFINITION") || ($1 == "PROCEDURE")) {
- split($2, parts, "[ (;]")
- ident = parts[1]
- sub($1"[ \t]+"ident, $1" <em>"ident"</em>", $0)
-}
-
-((commentLevel == 0) && match($0, /"|\(\*/)) || ((commentLevel > 0) && match($0, /\(\*|\*\)/)) {
- insideString = 0
- head = ""
- tail = $0
- do {
- delim = substr(tail, RSTART, RLENGTH)
- head = head""substr(tail, 1, RSTART - 1)
- if (delim == "\"") {
- if (! insideString) {
- head = head"<span class='string'>\""
- insideString = 1
- } else {
- head = head"\"</span>"
- insideString = 0
- }
- } else if (delim == "(*") {
- if (commentLevel == 0) {
- head = head"<span class='comment'>(*"
- } else {
- head = head"(*"
- }
- commentLevel++
- } else if (delim == "*)") {
- if (commentLevel == 1) {
- head = head"*)</span>"
- } else {
- head = head"*)"
- }
- commentLevel--
- } else {
- print "obncdoc-markup: invalid match" > "/dev/stderr"
- exit(1)
- }
- tail = substr(tail, RSTART + RLENGTH)
- if (insideString) {
- match(tail, /"/)
- } else if (commentLevel > 0) {
- match(tail, /\(\*|\*\)/)
- } else {
- match(tail, /"|\(\*|\*\)/)
- }
- } while (RSTART > 0)
- $0 = head""tail
-}
-
-{
- print $0
-}
+++ /dev/null
-#!/bin/sh
-
-# Copyright (C) 2017, 2018, 2019 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/>.
-
-printf "SKIPPED!!\n" >&2
-exit 0
-
-set -o errexit -o nounset
-
-readonly selfDirPath="$(cd "$(dirname "$0")"; pwd -P)"
-readonly packagePath="$(dirname "$selfDirPath")"
-readonly testDir="$packagePath/tests/obncdoc"
-
-(cd "$testDir" && "$selfDirPath/obncdoc")
-trap "rm -f '$testDir'/obncdoc/* && rmdir '$testDir/obncdoc'" INT TERM EXIT
-
-if ! diff -b "$testDir/obncdoc/NoExportedFeatures.def" "$testDir/NoExportedFeatures.def"; then
- echo "$(basename "$0") failed: files differ: $testDir/obncdoc/NoExportedFeatures.def" "$testDir/NoExportedFeatures.def" >&2
- exit 1
-fi
-
-if ! diff -b "$testDir/obncdoc/NoExportedFeatures.def.html" "$testDir/NoExportedFeatures.def.html"; then
- echo "$(basename "$0") failed: files differ: $testDir/obncdoc/NoExportedFeatures.def.html" "$testDir/NoExportedFeatures.def.html" >&2
- exit 1
-fi
-
-if ! diff -b "$testDir/obncdoc/ExportedFeatures.def" "$testDir/ExportedFeatures.def"; then
- echo "$(basename "$0") failed: files differ: $testDir/obncdoc/ExportedFeatures.def" "$testDir/ExportedFeatures.def" >&2
- exit 1
-fi
-
-if ! diff -b "$testDir/obncdoc/ExportedFeatures.def.html" "$testDir/ExportedFeatures.def.html"; then
- echo "$(basename "$0") failed: files differ: $testDir/obncdoc/ExportedFeatures.def.html" "$testDir/ExportedFeatures.def.html" >&2
- exit 1
-fi
cp obnc "$selfDirPath/bin"
fi
- #build path finder
- EchoAndRun cd "$selfDirPath/src"
- env CFLAGS="${CFLAGS:-}" "$selfDirPath/bin/micb" obnc-path.c
- if [ ! -e "$selfDirPath/bin/obnc-path" ] || [ "$selfDirPath/bin/obnc-path" -ot obnc-path ]; then
- cp obnc-path "$selfDirPath/bin"
- fi
-
- #build documentation generator
- EchoAndRun cd "$selfDirPath/src"
- env CFLAGS="${CFLAGS:-}" "$selfDirPath/bin/micb" obncdoc.c
- if [ ! -e "$selfDirPath/bin/obncdoc" ] || [ "$selfDirPath/bin/obncdoc" -ot obncdoc ]; then
- cp obncdoc "$selfDirPath/bin"
- fi
-
cd "$selfDirPath"
}
+++ /dev/null
-/*Copyright (C) 2017, 2018, 2019 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/>.*/
-
-#include "Config.h"
-#include "Error.h"
-#include "ModulePaths.h"
-#include "Paths.h"
-#include "Util.h"
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static void PrintHelp(void)
-{
- puts("obnc-path - print directory path for Oberon module");
- puts("");
- puts("usage:");
- puts("\tobnc-path [-v] MODULE");
- puts("\tobnc-path (-h | -v)");
- puts("");
- puts("\t-h\tdisplay help and exit");
- puts("\t-v\tprint each inspected directory, or display version and exit");
-}
-
-
-static void PrintVersion(void)
-{
- if (strcmp(CONFIG_VERSION, "") != 0) {
- printf("OBNC %s\n", CONFIG_VERSION);
- } else {
- puts("OBNC (unknown version)");
- }
-}
-
-
-static void PrintPath(const char module[], int verbose)
-{
- const char *dirPath;
-
- dirPath = ModulePaths_Directory(module, ".", verbose);
- if (dirPath != NULL) {
- puts(Paths_ShellArg(dirPath));
- } else {
- Error_Handle(Util_String("module not found: %s", module));
- }
-}
-
-
-static void ExitInvalidCommand(const char msg[])
-{
- assert(msg != NULL);
-
- if (strcmp(msg, "") != 0) {
- fprintf(stderr, "obnc-path: %s", msg);
- }
- fprintf(stderr, ". Try 'obnc-path -h' for more information.\n");
- exit(EXIT_FAILURE);
-}
-
-
-static void ExitFailure(const char msg[])
-{
- assert(msg != NULL);
-
- if (strcmp(msg, "") != 0) {
- fprintf(stderr, "obnc-path: %s\n", msg);
- }
- exit(EXIT_FAILURE);
-}
-
-
-int main(int argc, char *argv[])
-{
- int i;
- int helpWanted = 0;
- int vSet = 0;
- const char *module = NULL;
-
- Config_Init();
- Error_Init();
- ModulePaths_Init();
- Util_Init();
- Error_SetHandler(ExitInvalidCommand);
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-h") == 0) {
- helpWanted = 1;
- } else if (strcmp(argv[i], "-v") == 0) {
- vSet= 1;
- } else if ((argv[i][0] != '-') && (module == NULL)) {
- module = argv[i];
- } else {
- Error_Handle("invalid command");
- }
- }
-
- if (helpWanted) {
- PrintHelp();
- } else if (module != NULL) {
- if (strchr(module, '.') == NULL) {
- Error_SetHandler(ExitFailure);
- PrintPath(module, vSet);
- } else {
- Error_Handle("module name cannot contain '.'");
- }
- } else if (vSet) {
- PrintVersion();
- } else {
- Error_Handle("invalid command");
- }
-
- return 0;
-}
+++ /dev/null
-/*Copyright (C) 2017, 2018, 2019 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/>.*/
-
-#include "Config.h"
-#include "Error.h"
-#include "Files.h"
-#include "Paths.h"
-#include "Util.h"
-#include <dirent.h> /*POSIX*/
-#include <unistd.h> /*POSIX*/
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-typedef struct { int count; char **filenames; } Accumulator;
-
-typedef void (*Applicator)(const char filename[], Accumulator *acc);
-
-static void Apply(Applicator f, const char dirName[], Accumulator *acc) /*apply f on each file in directory dir with accumulator acc*/
-{
- DIR *dir;
- struct dirent *file;
- const char *filename;
- int error;
-
- assert(f != NULL);
- assert(dirName != NULL);
-
- dir = opendir(dirName);
- if (dir != NULL) {
- file = readdir(dir);
- while (file != NULL) {
- if ((strcmp(file->d_name, ".") != 0) && (strcmp(file->d_name, "..") != 0)) {
- filename = file->d_name;
- f(filename, acc);
- }
- file = readdir(dir);
- }
- error = closedir(dir);
- if (error) {
- Error_Handle(Util_String("closing directory failed: %s", strerror(errno)));
- }
- } else {
- Error_Handle(Util_String("reading directory failed: %s", strerror(errno)));
- }
-}
-
-
-static void ExitFailure(const char msg[])
-{
- assert(msg != NULL);
-
- if (strcmp(msg, "") != 0) {
- fprintf(stderr, "obncdoc: %s\n", msg);
- }
- fputs("obncdoc: generating documentation failed\n", stderr);
- exit(EXIT_FAILURE);
-}
-
-
-static void PrintHelp(void)
-{
- puts("obncdoc - extract exported features from Oberon modules");
- putchar('\n');
- puts("usage:");
- puts("\tobncdoc [-h | -v]");
- putchar('\n');
- puts("\t-h\tdisplay help and exit");
- puts("\t-v\tdisplay version and exit");
-}
-
-
-static void PrintVersion(void)
-{
- if (strcmp(CONFIG_VERSION, "") != 0) {
- printf("OBNC %s\n", CONFIG_VERSION);
- } else {
- puts("OBNC (unknown version)");
- }
-}
-
-
-static int EndsWith(const char pattern[], const char target[])
-{
- size_t patternLen = strlen(pattern);
- size_t targetLen = strlen(target);
-
- return (patternLen <= targetLen) && (strcmp(target + targetLen - patternLen, pattern) == 0);
-}
-
-
-static int IsOberonFile(const char filename[])
-{
- return EndsWith(".obn", filename) || EndsWith(".Mod", filename) || EndsWith(".mod", filename);
-}
-
-
-static const char *IndexTitle(void)
-{
- return Util_String("Index of %s", Paths_Basename(Paths_CurrentDir()));
-}
-
-
-static void PrintHtmlHeader(const char title[], FILE *file)
-{
- fputs("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n", file);
- fputs("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n", file);
- fputs(" <head>\n", file);
- fputs(" <meta name='viewport' content='width=device-width, initial-scale=1.0' />\n", file);
- fputs(" <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />\n", file);
- fprintf(file, " <title>%s</title>\n", title);
- fprintf(file, " <link rel='stylesheet' type='text/css' href='style.css' />\n");
- fputs(" </head>\n", file);
- fputs(" <body>\n", file);
-}
-
-
-static void PrintHtmlFooter(FILE *file)
-{
- fputs(" </body>\n", file);
- fputs("</html>\n", file);
-}
-
-
-static void CreateHtmlDefinition(const char module[], const char inputFile[], const char outputFile[])
-{
- const char *title, *script, *command;
- FILE *outFile;
- int error;
-
- title = Util_String("DEFINITION %s", module);
-
- if (Files_Exists(outputFile)) {
- outFile = Files_Old(outputFile, FILES_WRITE);
- } else {
- outFile = Files_New(outputFile);
- }
- PrintHtmlHeader(title, outFile);
- fprintf(outFile, " <p><a href='index.html'>Index</a></p>\n");
- fputc('\n', outFile);
- fputs(" <pre>\n", outFile);
- Files_Close(&outFile);
-
- script = Util_String("%s/bin/obncdoc-markup", Config_Prefix());
- command = Util_String("awk -f %s < %s >> %s", Paths_ShellArg(script), Paths_ShellArg(inputFile), Paths_ShellArg(outputFile));
- error = system(command);
- if (! error) {
- outFile = Files_Old(outputFile, FILES_APPEND);
- fputs("</pre>\n", outFile);
- PrintHtmlFooter(outFile);
- Files_Close(&outFile);
- } else {
- Files_Remove(outputFile);
- Error_Handle("");
- }
-}
-
-
-static void CreateDefinition(const char filename[], Accumulator *acc)
-{
- const char *oberonFile, *module, *textOutputFile, *htmlOutputFile, *scriptFile, *command;
- int error;
-
- assert(acc != NULL);
-
- if (IsOberonFile(filename)) {
- oberonFile = filename;
- module = Paths_SansSuffix(Paths_Basename(oberonFile));
- textOutputFile = Util_String("obncdoc/%s.def", module);
- htmlOutputFile = Util_String("obncdoc/%s.def.html", module);
-
- if (! Files_Exists(textOutputFile) || (Files_Timestamp(textOutputFile) < Files_Timestamp(oberonFile))) {
- scriptFile = Util_String("%s/bin/obncdoc-extract", Config_Prefix());
- command = Util_String("awk -f %s < %s > %s", Paths_ShellArg(scriptFile), oberonFile, textOutputFile);
- error = system(command);
- if (! error) {
- CreateHtmlDefinition(module, textOutputFile, htmlOutputFile);
- } else {
- Error_Handle("");
- }
- }
- acc->count++;
- }
-}
-
-
-static void CreateAllDefinitions(void)
-{
- Accumulator acc;
-
- if (! Files_Exists("obncdoc")) {
- Files_CreateDir("obncdoc");
- }
- acc.count = 0;
- Apply(CreateDefinition, ".", &acc);
- if (acc.count == 0) {
- Error_Handle("no oberon files");
- }
-}
-
-
-static void DeleteOrphanedDefinition(const char filename[], Accumulator *acc)
-{
- const char *module;
-
- (void) acc; /*unused*/
- if (strstr(filename, ".def") != NULL) {
- module = Paths_SansSuffix(Paths_Basename(filename));
- if (! Files_Exists(Util_String("%s.obn", module))
- && ! Files_Exists(Util_String("%s.Mod", module))
- && ! Files_Exists(Util_String("%s.mod", module))) {
- Files_Remove(Util_String("obncdoc/%s", filename));
- }
- }
-}
-
-
-static void DeleteAllOrphanedDefinitions(void)
-{
- Apply(DeleteOrphanedDefinition, "obncdoc", NULL);
-}
-
-
-static void CountDefinition(const char filename[], Accumulator *acc)
-{
- assert(filename != NULL);
- assert(acc != NULL);
-
- if (EndsWith(".def", filename)) {
- acc->count++;
- }
-}
-
-
-static void AddDefinition(const char filename[], Accumulator *acc)
-{
- if (EndsWith(".def", filename)) {
- acc->filenames[acc->count] = Util_String("%s", filename);
- acc->count++;
- }
-}
-
-
-static int StringComparison(const void *a, const void *b)
-{
- const char *s1 = *(const char **) a;
- const char *s2 = *(const char **) b;
-
- return strcmp(s1, s2);
-}
-
-
-static int DefFileEmpty(const char filename[])
-{
- FILE *f;
- int ch, newlineCount;
-
- f = Files_Old(filename, FILES_READ);
- newlineCount = 0;
- ch = fgetc(f);
- while ((ch != EOF) && (newlineCount <= 2)) {
- if (ch == '\n') {
- newlineCount++;
- }
- ch = fgetc(f);
- }
- Files_Close(&f);
- return newlineCount == 2;
-}
-
-
-static void CreateIndex(void)
-{
- const char *indexFilename = "obncdoc/index.html", *defFilename, *module;
- Accumulator acc;
- FILE *indexFile;
- int filenamesLen, i;
-
- /*count definition files*/
- acc.count = 0;
- Apply(CountDefinition, "obncdoc", &acc);
-
- /*add definition files to string array*/
- filenamesLen = acc.count;
- NEW_ARRAY(acc.filenames, filenamesLen);
- acc.count = 0;
- Apply(AddDefinition, "obncdoc", &acc);
- assert(acc.count == filenamesLen);
-
- /*sort definition files*/
- qsort(acc.filenames, filenamesLen, sizeof (char *), StringComparison);
-
- if (Files_Exists(indexFilename)) {
- indexFile = Files_Old(indexFilename, FILES_WRITE);
- } else {
- indexFile = Files_New(indexFilename);
- }
- PrintHtmlHeader(IndexTitle(), indexFile);
- fputs(" <p><a href='../index.html'>Index</a></p>\n", indexFile);
- fputc('\n', indexFile);
- fputs(" <pre>\n", indexFile);
- for (i = 0; i < filenamesLen; i++) {
- defFilename = acc.filenames[i];
- if (! DefFileEmpty(Util_String("obncdoc/%s", defFilename))) {
- module = Paths_SansSuffix(Paths_Basename(defFilename));
- fprintf(indexFile, "DEFINITION <a href='%s.def.html'>%s</a>\n", module, module);
- }
- }
- fputs(" </pre>\n", indexFile);
- PrintHtmlFooter(indexFile);
- Files_Close(&indexFile);
-}
-
-
-static void CreateCss(void)
-{
- const char *cssFile, *command;
- int error;
-
- if (! Files_Exists("obncdoc/style.css")) {
- cssFile = Util_String("%s/share/obnc/style.css", Config_Prefix());
-#ifdef _WIN32
- command = Util_String("copy %s obncdoc > NUL", Paths_ShellArg(Util_Replace("/", "\\", cssFile)));
-#else
- command = Util_String("cp %s obncdoc", Paths_ShellArg(cssFile));
-#endif
- error = system(command);
- if (error) {
- Error_Handle("");
- }
- }
-}
-
-
-static void CreateOutputFiles(void)
-{
- CreateAllDefinitions();
- DeleteAllOrphanedDefinitions();
- CreateIndex();
- CreateCss();
-}
-
-
-int main(int argc, char *argv[])
-{
- int i, helpWanted = 0, versionWanted = 0;
- const char *arg;
-
- Config_Init();
- Error_Init();
- Files_Init();
- Util_Init();
- Error_SetHandler(ExitFailure);
-
- for (i = 1; i < argc; i++) {
- arg = argv[i];
- if (strcmp(arg, "-h") == 0) {
- helpWanted = 1;
- } else if (strcmp(arg, "-v") == 0) {
- versionWanted = 1;
- } else {
- Error_Handle("Invalid command. Try 'obncdoc -h' for more information.");
- }
- }
- if (helpWanted) {
- PrintHelp();
- } else if (versionWanted) {
- PrintVersion();
- } else {
- CreateOutputFiles();
- }
- return 0;
-}