From patchwork Mon Nov 7 13:09:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gaius Mulley X-Patchwork-Id: 16411 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2039216wru; Mon, 7 Nov 2022 05:10:29 -0800 (PST) X-Google-Smtp-Source: AMsMyM4veRdTQcgWxzPlX//p2BYFidoDbApM1sKZKxC3L6ZNDfD/GFrDGO8CKOxZTeCvBz8UtSxX X-Received: by 2002:aa7:d59a:0:b0:45c:55f8:4fbf with SMTP id r26-20020aa7d59a000000b0045c55f84fbfmr730088edq.277.1667826629341; Mon, 07 Nov 2022 05:10:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667826629; cv=none; d=google.com; s=arc-20160816; b=cKKSu2baIYoQiLHxKahcQod3UqE9jv7KUYejBEuLzTq1bK3mOg2OrlbNrflz3y3qfj srGjgrylxhjbU15Wdgz3KRds5VzYKwtF7ZD+UoV8M1WUhnn30mofs3GOeKtl825TFw9m GbP/2a0qsLjl3Y0PzjqqR4LgOyNqO/GX3RFcMOgk0Fk4b9Fa7yK8rJeLqT08k8u55gwf RdkiyPTtmAuTlkIVszlw5YzMQdYVrWjTc3btWtKdaTS6cMEUc+qIctf/KhbuzxE02qcM UuTGf4ML2jw2xZT7u7JqFZLT1YG7JtvXCX2MYceq+wDuXmBfjwafTfAZFAfJlRWbfYMI HseQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:mime-version :user-agent:message-id:in-reply-to:date:references:subject:cc:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=+w50Qg7pPVbXQaKE/Cfa8JH68PFvac+M5Yr49KE/dzk=; b=PlPBFWIYxWcdMnAxAD+vCtZ4LPMkfFsv0PKBR/QZ0wmwIUkxbzlS3XJ1ZvEAow/ej9 UR3Usiu16iWXnH5/a/J/w0UMQf5E6TUjbgXgR9eD2SScLf507NvIVbI9t9M4NQITPRRZ UL1+F29TZhEvLzp1sE0/xbSu7tEx/unFat4M2ySkyMr8XvjjsUuSGc+j9eV+XmKKeheX HKY7wKzRDwDecxqoVYMHjl8teSKZWelDkoth6cGYIdUvzuEioHJNuVMWxwGLai6NjOdg N/DINVS9v+19oP5AUcZieZlNrRrmFM5Ax9xkYdYUAGpfrHkegqUjBlD1oL4Z+Gsqcp66 TH5Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=WtLLGJd4; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id ho11-20020a1709070e8b00b007ae754729d1si884122ejc.883.2022.11.07.05.10.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Nov 2022 05:10:29 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=WtLLGJd4; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 24F633858C74 for ; Mon, 7 Nov 2022 13:10:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 24F633858C74 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1667826628; bh=+w50Qg7pPVbXQaKE/Cfa8JH68PFvac+M5Yr49KE/dzk=; h=To:Cc:Subject:References:Date:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=WtLLGJd4hga7sw+eUKXeydm80wRS0gxYAyAzul8A/7TlPEeQKqFY4g0iM+DfWIySD M4kaDIiOu7YZkji3e2hKKrLLWxR9PnWx7Bem21ItpBK3fPukZWjx2NzVN9p8q2o8uE SSfctdIy2ul2lR+lM15UXsRFpiopOBipR0fTPy9E= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id 4CC023858D39 for ; Mon, 7 Nov 2022 13:09:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4CC023858D39 Received: by mail-wr1-x436.google.com with SMTP id o4so16144269wrq.6 for ; Mon, 07 Nov 2022 05:09:27 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:message-id:in-reply-to:date:references :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=+w50Qg7pPVbXQaKE/Cfa8JH68PFvac+M5Yr49KE/dzk=; b=V5NQzJnSzFD8o7y5XM/y36lT9viKSXYRz3IyuQL9uC+ON4JPGZzS/+E1d7FrLaZ1we zX+vYD9CnWyHtAqMEDbEWcUMJj6gYDOWEcZjaoGNnCGB6W4+FsuOD/Gd1k8PCd2O7wdi t9wNc0w2ts5uWlrB0RxFzRcFEQshO2ECRqAnOF58ksVmdYC34VyBgR/crn4zZ+hP0ngg +XiriUpwTOhyXjM4NTh6ahEvpBoXkc2fq4gTCk7dP+88a5O04tBAFyAY31IAtXT0xJP/ CYHJQE+HcG+IMlP0pvSXd264iPAYLni8po51XvYjZ4NH80Hl1I9t9w4eH7o6biqBwJOv E5Tg== X-Gm-Message-State: ACrzQf0ZJiJNnxzze05IFpYRJGYu8HA5pb74r5fQaEAFOQQXxRIo7AaK wh5DYFG03AHB6H0+gl2ycwo= X-Received: by 2002:adf:f784:0:b0:236:ea8:a410 with SMTP id q4-20020adff784000000b002360ea8a410mr550862wrp.128.1667826565047; Mon, 07 Nov 2022 05:09:25 -0800 (PST) Received: from lancelot ([195.147.220.46]) by smtp.gmail.com with ESMTPSA id p20-20020a05600c359400b003a6a3595edasm8643179wmq.27.2022.11.07.05.09.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Nov 2022 05:09:24 -0800 (PST) Received: from gaius by lancelot with local (Exim 4.94.2) (envelope-from ) id 1os1sO-00Chs1-Ka; Mon, 07 Nov 2022 13:09:20 +0000 To: Martin =?utf-8?b?TGnFoWth?= Cc: gcc-patches@gcc.gnu.org Subject: [PATCH v2 16/19] modula2 front end: bootstrap and documentation tools References: <11f42175-8e23-5da3-6a13-6172039bfca2@suse.cz> <87k052ppvq.fsf@debian> Date: Mon, 07 Nov 2022 13:09:20 +0000 In-Reply-To: <87k052ppvq.fsf@debian> (Gaius Mulley's message of "Fri, 14 Oct 2022 13:10:33 +0100") Message-ID: <87r0yesygv.fsf_-_@debian> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Gaius Mulley via Gcc-patches From: Gaius Mulley Reply-To: Gaius Mulley Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748842975690807049?= X-GMAIL-MSGID: =?utf-8?q?1748842975690807049?= Hi Martin, here is the revised patch having applied all previous recommendations: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603436.html Is this ok now? Thanks for the improvement suggestions (argparse results in fewer lines of code :-) regards, Gaius ------8<----------8<----------8<----------8<----------8<----------8<---- diff -ruw /dev/null gcc-git-devel-modula2/mliska@suse.cz diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/tidydates.py --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/tidydates.py 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 + +# utility to tidy dates and detect lack of copyright. + +# Copyright (C) 2016-2022 Free Software Foundation, Inc. +# +# This file is part of GNU Modula-2. +# +# GNU Modula-2 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, or (at your option) +# any later version. +# +# GNU Modula-2 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 GNU Modula-2; see the file COPYING. If not, write to the +# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +import os +import sys +import pathlib +import shutil + +maxLineLength = 60 + +COPYRIGHT = "Copyright (C)" + + +def visitDir(directory, ext, func): + # visitDir - call func for each file below, dir, matching extension, ext. + listOfFiles = os.listdir(directory) + listOfFiles.sort() + for filename in listOfFiles: + path = pathlib.PurePath(filename) + full = os.path.join(directory, filename) + if path.is_file(full): + if path.suffix == ext: + func(full) + elif path.is_dir(full): + visitDir(full, ext, func) + + +def isYear(year): + # isYear - returns True if, year, is legal. + if len(year) == 5: + year = year[:-1] + for c in year: + if not c.isdigit(): + return False + return True + + +def handleCopyright(outfile, lines, n, leader1, leader2): + # handleCopyright look for Copyright in the comment. + global maxLineLength + i = lines[n] + c = i.find(COPYRIGHT)+len(COPYRIGHT) + outfile.write(i[:c]) + d = i[c:].split() + start = c + seenDate = True + years = [] + while seenDate: + if d == []: + n += 1 + i = lines[n] + d = i[2:].split() + else: + e = d[0] + punctuation = "" + if len(d) == 1: + d = [] + else: + d = d[1:] + if c > maxLineLength: + outfile.write("\n") + outfile.write(leader1) + outfile.write(leader2) + outfile.write(" "*(start-2)) + c = start + if isYear(e): + if (e[-1] == ".") or (e[-1] == ","): + punctuation = e[-1] + e = e[:-1] + else: + punctuation = "" + else: + seenDate = False + if seenDate: + if not (e in years): + c += len(e) + len(punctuation) + outfile.write(" ") + outfile.write(e) + outfile.write(punctuation) + years += [e] + else: + if start < c: + outfile.write("\n") + outfile.write(leader1) + outfile.write(leader2) + outfile.write(" "*(start-2)) + + outfile.write(" ") + outfile.write(e) + outfile.write(punctuation) + for w in d: + outfile.write(" ") + outfile.write(w) + outfile.write("\n") + return outfile, n+1 + + +def handleHeader(filename, leader1, leader2): + # handleHeader reads in the header of a file and inserts + # a line break around the Copyright dates. + print("------------------------------") + lines = open(filename, "r").readlines() + if len(lines) > 20: + with open("tmptidy", "w") as outfile: + n = 0 + for i in lines: + if i.find("Copyright (C)") >= 0: + outfile, n = handleCopyright(outfile, lines, + n, leader1, leader2) + outfile.writelines(lines[n:]) + outfile.close() + print("-> mv tmptidy", filename) + shutil.move("tmptidy", filename) + return + else: + outfile.write(lines[n]) + n += 1 + sys.stdout.write("%s:1:1 needs a Copyright notice..\n" % filename) + + +def bashTidy(filename): + # bashTidy - tidy up dates using "#" comment + handleHeader(filename, "#", " ") + + +def cTidy(filename): + # cTidy - tidy up dates using "/* */" comments + handleHeader(filename, " ", "*") + + +def m2Tidy(filename): + # m2Tidy - tidy up dates using "(* *)" comments + handleHeader(filename, " ", " ") + + +def main(): + # main - for each file extension call the appropriate tidy routine. + visitDir(".", ".in", bashTidy) + visitDir(".", ".py", bashTidy) + visitDir(".", ".c", cTidy) + visitDir(".", ".h", cTidy) + visitDir(".", ".def", m2Tidy) + visitDir(".", ".mod", m2Tidy) + + +main() diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/boilerplate.py --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/boilerplate.py 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,548 @@ +#!/usr/bin/env python3 +# +# boilerplate.py utility to rewrite the boilerplate with new dates. +# +# Copyright (C) 2018-2022 Free Software Foundation, Inc. +# Contributed by Gaius Mulley . +# +# This file is part of GNU Modula-2. +# +# GNU Modula-2 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, or (at your option) +# any later version. +# +# GNU Modula-2 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 GNU Modula-2; see the file COPYING3. If not see +# . +# + +import argparse +import datetime +import os +import sys + + +errorCount = 0 +seenFiles = [] +outputName = None + +ISO_COPYRIGHT = "Copyright ISO/IEC" +COPYRIGHT = "Copyright (C)" +GNU_PUBLIC_LICENSE = "GNU General Public License" +GNU_LESSER_GENERAL = "GNU Lesser General" +GCC_RUNTIME_LIB_EXC = "GCC Runtime Library Exception" +VERSION_2_1 = "version 2.1" +VERSION_2 = "version 2" +VERSION_3 = "version 3" +Licenses = {VERSION_2_1: "v2.1", VERSION_2: "v2", VERSION_3: "v3"} +CONTRIBUTED_BY = "ontributed by" + + +def printf(fmt, *args): + # printf - keeps C programmers happy :-) + print(str(fmt) % args, end=' ') + + +def error(fmt, *args): + # error - issue an error message. + global errorCount + + print(str(fmt) % args, end=' ') + errorCount += 1 + + +def haltOnError(): + if errorCount > 0: + os.sys.exit(1) + + +def basename(f): + b = f.split("/") + return b[-1] + + +def analyseComment(text, f): + # analyseComment determine the license from the top comment. + start_date, end_date = None, None + contribution, summary, lic = None, None, None + if text.find(ISO_COPYRIGHT) > 0: + lic = "BSISO" + now = datetime.datetime.now() + for d in range(1984, now.year+1): + if text.find(str(d)) > 0: + if start_date is None: + start_date = str(d) + end_date = str(d) + return start_date, end_date, "", "", lic + elif text.find(COPYRIGHT) > 0: + if text.find(GNU_PUBLIC_LICENSE) > 0: + lic = "GPL" + elif text.find(GNU_LESSER_GENERAL) > 0: + lic = "LGPL" + for license in Licenses.keys(): + if text.find(license) > 0: + lic += Licenses[license] + if text.find(GCC_RUNTIME_LIB_EXC) > 0: + lic += "x" + now = datetime.datetime.now() + for d in range(1984, now.year+1): + if text.find(str(d)) > 0: + if start_date is None: + start_date = str(d) + end_date = str(d) + if text.find(CONTRIBUTED_BY) > 0: + i = text.find(CONTRIBUTED_BY) + i += len(CONTRIBUTED_BY) + j = text.index(". ", i) + contribution = text[i:j] + if text.find(basename(f)) > 0: + i = text.find(basename(f)) + j = text.find(". ", i) + if j < 0: + error('summary of the file does not finish with a "."') + summary = text[i:] + else: + summary = text[i:j] + return start_date, end_date, contribution, summary, lic + + +def analyseHeaderWithoutTerminator(f, start): + text = "" + for count, l in enumerate(open(f).readlines()): + parts = l.split(start) + if len(parts) > 1: + line = start.join(parts[1:]) + line = line.strip() + text += " " + text += line + elif (l.rstrip() != "") and (len(parts[0]) > 0): + return analyseComment(text, f), count + return [None, None, None, None, None], 0 + + +def analyseHeaderWithTerminator(f, start, end): + inComment = False + text = "" + for count, line in enumerate(open(f).readlines()): + while line != "": + line = line.strip() + if inComment: + text += " " + pos = line.find(end) + if pos >= 0: + text += line[:pos] + line = line[pos:] + inComment = False + else: + text += line + line = "" + else: + pos = line.find(start) + if (pos >= 0) and (len(line) > len(start)): + before = line[:pos].strip() + if before != "": + return analyseComment(text, f), count + line = line[pos + len(start):] + inComment = True + elif (line != "") and (line == end): + line = "" + else: + return analyseComment(text, f), count + return [None, None, None, None, None], 0 + + +def analyseHeader(f, start, end): + # analyseHeader - + if end is None: + return analyseHeaderWithoutTerminator(f, start) + else: + return analyseHeaderWithTerminator(f, start, end) + + +def addStop(sentence): + # addStop - add a full stop to a sentance. + if sentence is None: + return None + sentence = sentence.rstrip() + if (len(sentence) > 0) and (sentence[-1] != "."): + return sentence + "." + return sentence + + +GPLv3 = """ +%s + +Copyright (C) %s Free Software Foundation, Inc. +Contributed by %s + +This file is part of GNU Modula-2. + +GNU Modula-2 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, or (at your option) +any later version. + +GNU Modula-2 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 GNU Modula-2; see the file COPYING3. If not see +. +""" + +GPLv3x = """ +%s + +Copyright (C) %s Free Software Foundation, Inc. +Contributed by %s + +This file is part of GNU Modula-2. + +GNU Modula-2 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, or (at your option) +any later version. + +GNU Modula-2 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. +""" + +LGPLv3 = """ +%s + +Copyright (C) %s Free Software Foundation, Inc. +Contributed by %s + +This file is part of GNU Modula-2. + +GNU Modula-2 is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +GNU Modula-2 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with GNU Modula-2. If not, see . +""" + +BSISO = """ +Library module defined by the International Standard + Information technology - programming languages + BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language. + + Copyright ISO/IEC (International Organization for Standardization + and International Electrotechnical Commission) %s. + + It may be freely copied for the purpose of implementation (see page + 707 of the Information technology - Programming languages Part 1: + Modula-2, Base Language. BS ISO/IEC 10514-1:1996). +""" + +templates = {} +templates["GPLv3"] = GPLv3 +templates["GPLv3x"] = GPLv3x +templates["LGPLv3"] = LGPLv3 +templates["LGPLv2.1"] = LGPLv3 +templates["BSISO"] = BSISO + + +def writeTemplate(fo, magic, start, end, dates, contribution, summary, lic): + if lic in templates: + if lic == "BSISO": + # non gpl but freely distributed for the implementation of a + # compiler + text = templates[lic] % (dates) + text = text.rstrip() + else: + summary = summary.lstrip() + contribution = contribution.lstrip() + summary = addStop(summary) + contribution = addStop(contribution) + if magic is not None: + fo.write(magic) + fo.write("\n") + text = templates[lic] % (summary, dates, contribution) + text = text.rstrip() + if end is None: + text = text.split("\n") + for line in text: + fo.write(start) + fo.write(" ") + fo.write(line) + fo.write("\n") + else: + text = text.lstrip() + fo.write(start) + fo.write(" ") + fo.write(text) + fo.write(" ") + fo.write(end) + fo.write("\n") + # add a blank comment line for a script for eye candy. + if start == "#" and end is None: + fo.write(start) + fo.write("\n") + else: + error("no template found for: %s\n", lic) + os.sys.exit(1) + return fo + + +def writeBoilerPlate(fo, magic, start, end, + start_date, end_date, contribution, summary, gpl): + if start_date == end_date: + dates = start_date + else: + dates = "%s-%s" % (start_date, end_date) + return writeTemplate(fo, magic, start, end, + dates, contribution, summary, gpl) + + +def rewriteFile(f, magic, start, end, start_date, end_date, + contribution, summary, gpl, lines): + text = "".join(open(f).readlines()[lines:]) + if outputName == "-": + fo = sys.stdout + else: + fo = open(f, "w") + fo = writeBoilerPlate(fo, magic, start, end, + start_date, end_date, contribution, summary, gpl) + fo.write(text) + fo.flush() + if outputName != "-": + fo.close() + + +def handleHeader(f, magic, start, end): + # handleHeader keep reading lines of file, f, looking for start, end + # sequences and comments inside. The comments are checked for: + # date, contribution, summary + global errorCount + + errorCount = 0 + [start_date, end_date, + contribution, summary, lic], lines = analyseHeader(f, start, end) + if lic is None: + error("%s:1:no GPL found at the top of the file\n", f) + else: + if args.verbose: + printf("copyright: %s\n", lic) + if (start_date is not None) and (end_date is not None): + if start_date == end_date: + printf("dates = %s\n", start_date) + else: + printf("dates = %s-%s\n", start_date, end_date) + if summary is not None: + printf("summary: %s\n", summary) + if contribution is not None: + printf("contribution: %s\n", contribution) + if start_date is None: + error("%s:1:no date found in the GPL at the top of the file\n", f) + if args.contribution is None: + if contribution == "": + error("%s:1:no contribution found in the " + + "GPL at the top of the file\n", f) + else: + contribution = args.contribution + if summary is None: + if args.summary == "": + error("%s:1:no single line summary found in the " + + "GPL at the top of the file\n", f) + else: + summary = args.summary + if errorCount == 0: + now = datetime.datetime.now() + if args.no: + print(f, "suppressing change as requested: %s-%s %s" + % (start_date, end_date, lic)) + else: + if lic == "BSISO": + # don't change the BS ISO license! + pass + elif args.extensions: + lic = "GPLv3x" + elif args.gpl3: + lic = "GPLv3" + rewriteFile(f, magic, start, end, start_date, + str(now.year), contribution, summary, lic, lines) + else: + printf("too many errors, no modifications will occur\n") + + +def bashTidy(f): + # bashTidy tidy up dates using '#' comment + handleHeader(f, "#!/bin/bash", "#", None) + + +def pythonTidy(f): + # pythonTidy tidy up dates using '#' comment + handleHeader(f, "#!/usr/bin/env python3", '#', None) + + +def bnfTidy(f): + # bnfTidy tidy up dates using '--' comment + handleHeader(f, None, '--', None) + + +def cTidy(f): + # cTidy tidy up dates using '/* */' comments + handleHeader(f, None, '/*', '*/') + + +def m2Tidy(f): + # m2Tidy tidy up dates using '(* *)' comments + handleHeader(f, None, '(*', '*)') + + +def inTidy(f): + # inTidy tidy up dates using '#' as a comment and check + # the first line for magic number. + first = open(f).readlines()[0] + if (len(first) > 0) and (first[:2] == "#!"): + # magic number found, use this + handleHeader(f, first, "#", None) + else: + handleHeader(f, None, "#", None) + + +def doVisit(args, dirname, names): + # doVisit helper function to call func on every extension file. + global outputName + func, extension = args + for f in names: + if len(f) > len(extension) and f[-len(extension):] == extension: + outputName = f + func(os.path.join(dirname, f)) + + +def visitDir(startDir, ext, func): + # visitDir call func for each file in startDir which has ext. + global outputName, seenFiles + for dirName, subdirList, fileList in os.walk(startDir): + for fname in fileList: + if (len(fname) > len(ext)) and (fname[-len(ext):] == ext): + fullpath = os.path.join(dirName, fname) + outputName = fullpath + if not (fullpath in seenFiles): + seenFiles += [fullpath] + func(fullpath) + # Remove the first entry in the list of sub-directories + # if there are any sub-directories present + if len(subdirList) > 0: + del subdirList[0] + + +def findFiles(): + # findFiles for each file extension call the appropriate tidy routine. + visitDir(args.recursive, '.h.in', cTidy) + visitDir(args.recursive, '.in', inTidy) + visitDir(args.recursive, '.sh', inTidy) + visitDir(args.recursive, '.py', pythonTidy) + visitDir(args.recursive, '.c', cTidy) + visitDir(args.recursive, '.h', cTidy) + visitDir(args.recursive, '.cc', cTidy) + visitDir(args.recursive, '.def', m2Tidy) + visitDir(args.recursive, '.mod', m2Tidy) + visitDir(args.recursive, '.bnf', bnfTidy) + + +def handleArguments(): + # handleArguments create and return the args object. + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--contribution", + help="set the contribution string " + + "at the top of the file.", + default="", action="store") + parser.add_argument("-d", "--debug", help="turn on internal debugging.", + default=False, action="store_true") + parser.add_argument("-f", "--force", + help="force a check to insist that the " + + "contribution, summary and GPL exist.", + default=False, action="store_true") + parser.add_argument("-g", "--gplv3", help="change to GPLv3", + default=False, action="store_true") + parser.add_argument("-o", "--outputfile", help="set the output file", + default="-", action="store") + parser.add_argument("-r", "--recursive", + help="recusively scan directory for known file " + + "extensions (.def, .mod, .c, .h, .py, .in, .sh).", + default=".", action="store") + parser.add_argument("-s", "--summary", + help="set the summary line for the file.", + default=None, action="store") + parser.add_argument("-u", "--update", help="update all dates.", + default=False, action="store_true") + parser.add_argument("-v", "--verbose", + help="display copyright, " + + "date and contribution messages", + action="store_true") + parser.add_argument("-x", "--extensions", + help="change to GPLv3 with GCC runtime extensions.", + default=False, action="store_true") + parser.add_argument("-N", "--no", + help="do not modify any file.", + action="store_true") + args = parser.parse_args() + return args + + +def hasExt(name, ext): + # hasExt return True if, name, ends with, ext. + if len(name) > len(ext): + return name[-len(ext):] == ext + return False + + +def singleFile(name): + # singleFile scan the single file for a GPL boilerplate which + # has a GPL, contribution field and a summary heading. + if hasExt(name, ".def") or hasExt(name, ".mod"): + m2Tidy(name) + elif hasExt(name, ".h") or hasExt(name, ".c") or hasExt(name, ".cc"): + cTidy(name) + elif hasExt(name, ".in"): + inTidy(name) + elif hasExt(name, ".sh"): + inTidy(name) # uses magic number for actual sh/bash + elif hasExt(name, ".py"): + pythonTidy(name) + + +def main(): + # main - handleArguments and then find source files. + global args, outputName + args = handleArguments() + outputName = args.outputfile + if args.recursive: + findFiles() + elif args.inputfile is None: + print("an input file must be specified on the command line") + else: + singleFile(args.inputfile) + haltOnError() + + +main() diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/buildpg --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/buildpg 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,289 @@ +#!/bin/sh + +# Copyright (C) 2000-2022 Free Software Foundation, Inc. +# This file is part of GNU Modula-2. +# +# GNU Modula-2 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, or (at your option) +# any later version. +# +# GNU Modula-2 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 GNU Modula-2; see the file COPYING. If not, write to the +# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. +# + +# builds the pg.bnf from ppg.mod +# usage buildpg ppg.mod destination [-e] +# -e build without error recovery +# +PPGSRC=$1 +PPGDST=$2 + +includeNonErrorChecking () { + sed -e "1,/StartNonErrorChecking/d" < $PPGSRC |\ + sed -e "1,/EndNonErrorChecking/!d" +} + +includeErrorChecking () { + sed -e "1,/StartErrorChecking/d" < $PPGSRC |\ + sed -e "1,/EndErrorChecking/!d" +} + + +echo "% module" $PPGDST "begin" +sed -e "1,/% declaration/!d" < $PPGSRC | sed -e "s/ppg/${PPGDST}/g" + +echo "% declaration" $PPGDST "begin" + +sed -e "1,/% declaration/d" < $PPGSRC | sed -e "1,/% rules/!d" | sed -e "s/ppg/${PPGDST}/g" + +if [ "$3" = "-e" ] ; then + includeNonErrorChecking + echo "% module" $PPGDST "end" + sed -e "1,/% module pg end/d" < $PPGSRC | sed -e "s/ppg/${PPGDST}/g" +else + includeErrorChecking + echo "% module" $PPGDST "end" + sed -e "1,/% module pg end/d" < $PPGSRC | sed -e "s/ppg/${PPGDST}/g" |\ + sed -e "s/WasNoError := Main() ;/Main({eoftok}) ;/" +fi + +echo "% rules" + +cat << EOFEOF | sed -e "s/ppg/${PPGDST}/g" +error 'WarnError' 'WarnString' +tokenfunc 'GetCurrentTokenType()' + +token 'identifier' identtok -- internal token +token 'literal' literaltok +token '%' codetok +token ':=' lbecomestok +token '=:' rbecomestok +token '|' bartok +token '[' lsparatok +token ']' rsparatok +token '{' lcparatok -- left curly para +token '}' rcparatok -- right curly para +token '(' lparatok +token ')' rparatok +token "error" errortok +token "tokenfunc" tfunctok +token "symfunc" symfunctok +token '"' dquotetok +token "'" squotetok +token "module" moduletok +token "begin" begintok +token "rules" rulestok +token "end" endtok +token '<' lesstok +token '>' gretok +token "token" tokentok +token "special" specialtok +token "first" firsttok +token "follow" followtok +token "BNF" BNFtok +token "FNB" FNBtok +token "declaration" declarationtok +token "epsilon" epsilontok +token '' eoftok -- internal token + +special Ident first { < identtok > } follow { } +special Modula2Code first { } follow { '%' } +special StartModName first { < identtok > } follow { } +special EndModName first { < identtok > } follow { } +special DoDeclaration first { < identtok > } follow { } +special CollectLiteral first { < literaltok > } follow { } +special CollectTok first { < identtok > } follow { } +special DefineToken first { < identtok > } follow { } + +BNF + +Rules := "%" "rules" { Defs } ExtBNF =: + +Special := Ident + % VAR p: ProductionDesc ; % + % p := NewProduction() ; + p^.statement := NewStatement() ; + p^.statement^.followinfo^.calcfollow := TRUE ; + p^.statement^.followinfo^.epsilon := false ; + p^.statement^.followinfo^.reachend := false ; + p^.statement^.ident := CurrentIdent ; + p^.statement^.expr := NIL ; + p^.firstsolved := TRUE ; + p^.followinfo^.calcfollow := TRUE ; + p^.followinfo^.epsilon := false ; + p^.followinfo^.reachend := false % + First Follow [ "epsilon" % p^.statement^.followinfo^.epsilon := true ; (* these are not used - but they are displayed when debugging *) + p^.statement^.followinfo^.reachend := true ; + p^.followinfo^.epsilon := true ; + p^.followinfo^.reachend := true + % ] + [ Literal % p^.description := LastLiteral % ] + =: + +Factor := "%" Modula2Code "%" | + Ident % WITH CurrentFactor^ DO + type := id ; + ident := CurrentIdent + END ; % | + Literal % WITH CurrentFactor^ DO + type := lit ; + string := LastLiteral ; + IF GetSymKey(Aliases, LastLiteral)=NulName + THEN + WarnError1('no token defined for literal %s', LastLiteral) + END + END ; % | + "{" % WITH CurrentFactor^ DO + type := mult ; + expr := NewExpression() ; + CurrentExpression := expr ; + END ; % + Expression "}" | + "[" % WITH CurrentFactor^ DO + type := opt ; + expr := NewExpression() ; + CurrentExpression := expr ; + END ; % + Expression "]" | + "(" % WITH CurrentFactor^ DO + type := sub ; + expr := NewExpression() ; + CurrentExpression := expr ; + END ; % + Expression ")" =: + +Statement := % VAR i: IdentDesc ; % + Ident + % VAR p: ProductionDesc ; % + % p := FindDefinition(CurrentIdent^.name) ; + IF p=NIL + THEN + p := NewProduction() + ELSE + IF NOT ((p^.statement=NIL) OR (p^.statement^.expr=NIL)) + THEN + WarnError1('already declared rule %s', CurrentIdent^.name) + END + END ; + i := CurrentIdent ; % + ":=" + % VAR e: ExpressionDesc ; % + % e := NewExpression() ; + CurrentExpression := e ; % + % VAR s: StatementDesc ; % + % s := NewStatement() ; + WITH s^ DO + ident := i ; + expr := e + END ; % + Expression + % p^.statement := s ; % + "=:" =: + +Defs := "special" Special | "token" Token | "error" ErrorProcedures | + "tokenfunc" TokenProcedure | "symfunc" SymProcedure =: +ExtBNF := "BNF" { Production } "FNB" =: +Main := Header Decls Footer Rules =: +Header := "%" "module" StartModName =: +Decls := "%" "declaration" DoDeclaration =: +Footer := "%" "module" EndModName =: + +First := "first" "{" { LitOrTokenOrIdent + % WITH CurrentSetDesc^ DO + next := TailProduction^.first ; + END ; + TailProduction^.first := CurrentSetDesc + % + } "}" =: +Follow := "follow" "{" { LitOrTokenOrIdent + % WITH CurrentSetDesc^ DO + next := TailProduction^.followinfo^.follow ; + END ; + TailProduction^.followinfo^.follow := CurrentSetDesc + % + } "}" =: +LitOrTokenOrIdent := Literal % CurrentSetDesc := NewSetDesc() ; + WITH CurrentSetDesc^ DO + type := litel ; + string := LastLiteral ; + END ; + % | + '<' CollectTok '>' | + Ident % CurrentSetDesc := NewSetDesc() ; + WITH CurrentSetDesc^ DO + type := idel ; + ident := CurrentIdent ; + END ; + % =: + +Literal := '"' CollectLiteral '"' | + "'" CollectLiteral "'" =: + +CollectTok := % CurrentSetDesc := NewSetDesc() ; + WITH CurrentSetDesc^ DO + type := tokel ; + string := GetCurrentToken() ; + END ; + IF NOT ContainsSymKey(Values, GetCurrentToken()) + THEN + AddEntry(Values, GetCurrentToken(), LargestValue) ; + AddEntry(ReverseValues, Name(LargestValue), GetCurrentToken()) ; + AddEntry(Aliases, GetCurrentToken(), GetCurrentToken()) ; + AddEntry(ReverseAliases, GetCurrentToken(), GetCurrentToken()) ; + INC(LargestValue) + END ; + AdvanceToken() ; % =: + +CollectLiteral := % LastLiteral := GetCurrentToken() ; + AdvanceToken ; % =: + +DefineToken := % AddEntry(Aliases, LastLiteral, GetCurrentToken()) ; + AddEntry(ReverseAliases, GetCurrentToken(), LastLiteral) ; + AddEntry(Values, GetCurrentToken(), LargestValue) ; + AddEntry(ReverseValues, Name(LargestValue), GetCurrentToken()) ; + INC(LargestValue) ; + AdvanceToken ; % =: + +Token := Literal DefineToken =: + +ErrorProcedures := Literal % ErrorProcArray := LastLiteral % + Literal % ErrorProcString := LastLiteral % =: +TokenProcedure := Literal % TokenTypeProc := LastLiteral % =: +SymProcedure := Literal % SymIsProc := LastLiteral % =: + +Production := Statement =: +Expression := % VAR t1, t2: TermDesc ; + e : ExpressionDesc ; % + % e := CurrentExpression ; + t1 := NewTerm() ; + CurrentTerm := t1 ; % + Term % e^.term := t1 ; % + { "|" % t2 := NewTerm() ; + CurrentTerm := t2 % + Term % t1^.next := t2 ; + t1 := t2 % } =: + +Term := % VAR t1: TermDesc ; f1, f2: FactorDesc ; % + % CurrentFactor := NewFactor() ; + f1 := CurrentFactor ; + t1 := CurrentTerm ; % + Factor % t1^.factor := f1 ; + f2 := NewFactor() ; + CurrentFactor := f2 % + { Factor % f1^.next := f2 ; + f1 := f2 ; + f2 := NewFactor() ; + CurrentFactor := f2 ; % } + =: + +FNB + +EOFEOF diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/calcpath --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/calcpath 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,51 @@ +#!/bin/sh + +# calcpath return a path which is $1/$2/$3 when $2 is relative and $2/$3 if absolute. + +# Copyright (C) 2021-2022 Free Software Foundation, Inc. +# Contributed by Gaius Mulley . +# +# This file is part of GNU Modula-2. +# +# GNU Modula-2 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, or (at your option) any later +# version. +# +# GNU Modula-2 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 gm2; see the file COPYING. If not, write to the Free Software +# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) + + +Usage () { + echo "Usage: calcpath pathcomponent1 pathcomponent2 subdir" + echo -n " if pathcomponent1 is relative then pathcomponent1/pathcomponet2/subdir is" + echo " returned" + echo " otherwise pathcomponet2/subdir is returned" + echo " the path is checked for legality in subdir." +} + + +if [ $# -eq 3 ]; then + if [ "$(echo $2 | cut -b 1)" = "." ] ; then + # relative path + the_path=$1/$2/$3 + else + the_path=$2/$3 + fi + cd $3 + if realpath ${the_path} > /dev/null ; then + echo ${the_path} + else + echo "calcpath: error ${the_path} is not a valid path in subdirectory $3" 1>&2 + exit 1 + fi +else + Usage + exit 1 +fi diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/makeSystem --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/makeSystem 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,108 @@ +#!/bin/sh + +# makeSystem creates a target SYSTEM.def using the appropriate dialect template. + +# Copyright (C) 2008-2022 Free Software Foundation, Inc. +# Contributed by Gaius Mulley . +# +# This file is part of GNU Modula-2. +# +# GNU Modula-2 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, or (at your option) any later +# version. +# +# GNU Modula-2 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 gm2; see the file COPYING. If not, write to the Free Software +# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) + + +Usage () { + echo "Usage: makesystem dialectflag SYSTEM.def SYSTEM.mod librarypath compiler" +} + +if [ $# -lt 6 ] ; then + Usage + exit 1 +fi + +DIALECT=$1 +SYSTEMDEF=$2 +SYSTEMMOD=$3 +LIBRARY=$4 +COMPILER=$5 +OUTPUTFILE=$6 + +if [ "$COMPILER" = "" ] ; then + echo "parameter 5 of makeSystem is incorrect, GM2_FOR_TARGET was unset" + exit 1 +fi + +if [ "$DIALECT" != "-fiso" -a "$DIALECT" != "-fpim" ] ; then + Usage + echo "dialect must be -fiso or -fpim" + exit 1 +fi + +displayExportedTypes () { + n=1 + c=0 + for i in ${types} ; do + if [ $n -eq 1 ] ; then + n=0 + echo -n " " >> ${OUTPUTFILE} + fi + echo -n "$i, " >> ${OUTPUTFILE} + if [ $c -eq 4 ] ; then + echo " " >> ${OUTPUTFILE} + n=1 + c=0 + fi + c=`expr $c + 1` + done + echo " " >> ${OUTPUTFILE} +} + +displayBuiltinTypes () { + for i in ${types} ; do + echo " $i ; " >> ${OUTPUTFILE} + done +} + +displayStart () { + sed -e "1,/@SYSTEM_DATATYPES@/!d" < ${SYSTEMDEF} | \ + sed -e "/@SYSTEM_DATATYPES@/d" >> ${OUTPUTFILE} +} + +displayMiddle () { + sed -e "1,/@SYSTEM_DATATYPES@/d" < ${SYSTEMDEF} | \ + sed -e "1,/@SYSTEM_TYPES@/!d" | \ + sed -e "/@SYSTEM_TYPES@/d" >> ${OUTPUTFILE} +} + +displayEnd () { + sed -e "1,/@SYSTEM_TYPES@/d" < ${SYSTEMDEF} >> ${OUTPUTFILE} +} + +MINIMAL="-fno-scaffold-main -fno-scaffold-dynamic -fno-scaffold-static -fno-m2-plugin" + +rm -f ${OUTPUTFILE} +if ${COMPILER} ${DIALECT} ${LIBRARY} ${MINIMAL} \ + -c -fdump-system-exports ${SYSTEMMOD} -o /dev/null 2>&1 > /dev/null ; then + types=`${COMPILER} ${DIALECT} ${LIBRARY} ${MINIMAL} -fno-m2-plugin -c -fdump-system-exports ${SYSTEMMOD} -o /dev/null | cut -f5 -d' '` + touch ${OUTPUTFILE} + displayStart + displayExportedTypes + displayMiddle + displayBuiltinTypes + displayEnd +else + ${COMPILER} ${DIALECT} ${LIBRARY} ${MINIMAL} \ + -c -fdump-system-exports ${SYSTEMMOD} -o /dev/null + exit $? +fi diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/README --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/README 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,3 @@ +This directory contains miscellaneous scripts and programs (mklink.c) +to allow for bootstrap linking and creating library documentation from +sources. \ No newline at end of file diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/def2doc.py --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/def2doc.py 2022-11-05 17:33:53.685584357 +0000 @@ -0,0 +1,419 @@ +#!/usr/bin/env python3 + +# def2doc.py creates texi library documentation for all exported procedures. +# Contributed by Gaius Mulley . + +# Copyright (C) 2000-2022 Free Software Foundation, Inc. +# This file is part of GNU Modula-2. +# +# GNU Modula-2 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, or (at your option) +# any later version. +# +# GNU Modula-2 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 GNU Modula-2; see the file COPYING. If not, write to the +# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. +# + +import argparse +import os +import sys + +BaseLibs = ["gm2-libs", "Base libraries", "Basic M2F compatible libraries"] + +PIMLogDesc = "PIM and Logitech 3.0 compatible libraries" +PIMLog = ["gm2-libs-pim", "PIM and Logitech 3.0 Compatible", PIMLogDesc] +PIMCorDesc = "PIM compatible process support" +PIMCor = ["gm2-libs-coroutines", "PIM coroutine support", PIMCorDesc] +ISOLibs = ["gm2-libs-iso", "M2 ISO Libraries", "ISO defined libraries"] + +libraryClassifications = [BaseLibs, PIMLog, PIMCor, ISOLibs] + + +def initState(): + global inVar, inType, inConst + inVar, inType, inConst = False, False, False + + +def emitNode(name, nxt, previous, up): + if args.texinfo: + output.write("@node " + name + ", " + nxt + ", ") + output.write(previous + ", " + up + "\n") + elif args.sphinx: + output.write("@c @node " + name + ", " + nxt + ", ") + output.write(previous + ", " + up + "\n") + + +def emitSection(name): + if args.texinfo: + output.write("@section " + name + "\n") + elif args.sphinx: + output.write(name + "\n") + output.write("=" * len(name) + "\n") + + +def emitSubSection(name): + if args.texinfo: + output.write("@subsection " + name + "\n") + elif args.sphinx: + output.write(name + "\n") + output.write("-" * len(name) + "\n") + + +def displayLibraryClass(): + # displayLibraryClass displays a node for a library directory and invokes + # a routine to summarize each module. + global args + previous = "" + nxt = libraryClassifications[1][1] + i = 0 + lib = libraryClassifications[i] + while True: + emitNode(lib[1], nxt, previous, args.up) + emitSection(lib[1]) + output.write("\n") + displayModules(lib[1], lib[0], args.builddir, args.sourcedir) + output.write("\n") + output.write("@c " + "-" * 60 + "\n") + previous = lib[1] + i += 1 + if i == len(libraryClassifications): + break + lib = libraryClassifications[i] + if i+1 == len(libraryClassifications): + nxt = "" + else: + nxt = libraryClassifications[i+1][1] + + +def displayMenu(): + # displayMenu displays the top level menu for library documentation. + output.write("@menu\n") + for lib in libraryClassifications: + output.write("* " + lib[1] + "::" + lib[2] + "\n") + output.write("@end menu\n") + output.write("\n") + output.write("@c " + "=" * 60 + "\n") + output.write("\n") + + +def removeInitialComments(file, line): + # removeInitialComments removes any (* *) at the top + # of the definition module. + while (str.find(line, "*)") == -1): + line = file.readline() + + +def removeableField(line): + # removeableField - returns True if a comment field should be removed + # from the definition module. + field_list = ["Author", "Last edit", "LastEdit", "Last update", + "Date", "Title", "Revision"] + for field in field_list: + if (str.find(line, field) != -1) and (str.find(line, ":") != -1): + return True + ignore_list = ["System", "SYSTEM"] + for ignore_field in ignore_list: + if str.find(line, ignore_field) != -1: + if str.find(line, ":") != -1: + if str.find(line, "Description:") == -1: + return True + return False + + +def removeFields(file, line): + # removeFields removes Author/Date/Last edit/SYSTEM/Revision + # fields from a comment within the start of a definition module. + while (str.find(line, "*)") == -1): + if not removeableField(line): + output.write(str.replace(str.replace(str.rstrip(line), + "{", "@{"), "}", "@}") + "\n") + line = file.readline() + output.write(str.rstrip(line) + "\n") + + +def checkIndex(line): + # checkIndex - create an index entry for a PROCEDURE, TYPE, CONST or VAR. + global inVar, inType, inConst + + words = str.split(line) + procedure = "" + if (len(words) > 1) and (words[0] == "PROCEDURE"): + inConst = False + inType = False + inVar = False + if (words[1] == "__BUILTIN__") and (len(words) > 2): + procedure = words[2] + else: + procedure = words[1] + if (len(line) > 1) and (line[0:2] == "(*"): + inConst = False + inType = False + inVar = False + elif line == "VAR": + inConst = False + inVar = True + inType = False + return + elif line == "TYPE": + inConst = False + inType = True + inVar = False + return + elif line == "CONST": + inConst = True + inType = False + inVar = False + if inVar: + words = str.split(line, ",") + for word in words: + word = str.lstrip(word) + if word != "": + if str.find(word, ":") == -1: + output.write("@findex " + word + " (var)\n") + elif len(word) > 0: + var = str.split(word, ":") + if len(var) > 0: + output.write("@findex " + var[0] + " (var)\n") + + if inType: + words = str.lstrip(line) + if str.find(words, "=") != -1: + word = str.split(words, "=") + if (len(word[0]) > 0) and (word[0][0] != "_"): + output.write("@findex " + str.rstrip(word[0]) + " (type)\n") + else: + word = str.split(words) + if (len(word) > 1) and (word[1] == ";"): + # hidden type + if (len(word[0]) > 0) and (word[0][0] != "_"): + output.write("@findex " + str.rstrip(word[0])) + output.write(" (type)\n") + if inConst: + words = str.split(line, ";") + for word in words: + word = str.lstrip(word) + if word != "": + if str.find(word, "=") != -1: + var = str.split(word, "=") + if len(var) > 0: + output.write("@findex " + var[0] + " (const)\n") + if procedure != "": + name = str.split(procedure, "(") + if name[0] != "": + proc = name[0] + if proc[-1] == ";": + proc = proc[:-1] + if proc != "": + output.write("@findex " + proc + "\n") + + +def parseDefinition(dir, source, build, file, needPage): + # parseDefinition reads a definition module and creates + # indices for procedures, constants, variables and types. + output.write("\n") + with open(findFile(dir, build, source, file), "r") as f: + initState() + line = f.readline() + while (str.find(line, "(*") != -1): + removeInitialComments(f, line) + line = f.readline() + while (str.find(line, "DEFINITION") == -1): + line = f.readline() + output.write("@example\n") + output.write(str.rstrip(line) + "\n") + line = f.readline() + if len(str.rstrip(line)) == 0: + output.write("\n") + line = f.readline() + if (str.find(line, "(*") != -1): + removeFields(f, line) + else: + output.write(str.rstrip(line) + "\n") + else: + output.write(str.rstrip(line) + "\n") + line = f.readline() + while line: + line = str.rstrip(line) + checkIndex(line) + output.write(str.replace(str.replace(line, "{", "@{"), "}", "@}")) + output.write("\n") + line = f.readline() + output.write("@end example\n") + if needPage: + output.write("@page\n") + + +def parseModules(up, dir, build, source, listOfModules): + previous = "" + i = 0 + if len(listOfModules) > 1: + nxt = dir + "/" + listOfModules[1][:-4] + else: + nxt = "" + while i < len(listOfModules): + emitNode(dir + "/" + listOfModules[i][:-4], nxt, previous, up) + emitSubSection(dir + "/" + listOfModules[i][:-4]) + parseDefinition(dir, source, build, listOfModules[i], True) + output.write("\n") + previous = dir + "/" + listOfModules[i][:-4] + i = i + 1 + if i+1 < len(listOfModules): + nxt = dir + "/" + listOfModules[i+1][:-4] + else: + nxt = "" + + +def doCat(name): + # doCat displays the contents of file, name, to stdout + with open(name, "r") as file: + line = file.readline() + while line: + output.write(str.rstrip(line) + "\n") + line = file.readline() + + +def moduleMenu(dir, build, source): + # moduleMenu generates a simple menu for all definition modules + # in dir + output.write("@menu\n") + listOfFiles = [] + if os.path.exists(os.path.join(source, dir)): + listOfFiles += os.listdir(os.path.join(source, dir)) + if os.path.exists(os.path.join(source, dir)): + listOfFiles += os.listdir(os.path.join(build, dir)) + listOfFiles = list(dict.fromkeys(listOfFiles).keys()) + listOfFiles.sort() + for file in listOfFiles: + if foundFile(dir, build, source, file): + if (len(file) > 4) and (file[-4:] == ".def"): + output.write("* " + dir + "/" + file[:-4] + "::" + file + "\n") + output.write("@end menu\n") + output.write("\n") + + +def checkDirectory(dir, build, source): + # checkDirectory - returns True if dir exists in either build or source. + if os.path.isdir(build) and os.path.exists(os.path.join(build, dir)): + return True + elif os.path.isdir(source) and os.path.exists(os.path.join(source, dir)): + return True + else: + return False + + +def foundFile(dir, build, source, file): + # foundFile return True if file is found in build/dir/file or + # source/dir/file. + name = os.path.join(os.path.join(build, dir), file) + if os.path.exists(name): + return True + name = os.path.join(os.path.join(source, dir), file) + if os.path.exists(name): + return True + return False + + +def findFile(dir, build, source, file): + # findFile return the path to file searching in build/dir/file + # first then source/dir/file. + name1 = os.path.join(os.path.join(build, dir), file) + if os.path.exists(name1): + return name1 + name2 = os.path.join(os.path.join(source, dir), file) + if os.path.exists(name2): + return name2 + sys.stderr.write("file cannot be found in either " + name1) + sys.stderr.write(" or " + name2 + "\n") + os.sys.exit(1) + + +def displayModules(up, dir, build, source): + # displayModules walks though the files in dir and parses + # definition modules and includes README.texi + if checkDirectory(dir, build, source): + if foundFile(dir, build, source, "README.texi"): + doCat(findFile(dir, build, source, "README.texi")) + moduleMenu(dir, build, source) + listOfFiles = [] + if os.path.exists(os.path.join(source, dir)): + listOfFiles += os.listdir(os.path.join(source, dir)) + if os.path.exists(os.path.join(source, dir)): + listOfFiles += os.listdir(os.path.join(build, dir)) + listOfFiles = list(dict.fromkeys(listOfFiles).keys()) + listOfFiles.sort() + listOfModules = [] + for file in listOfFiles: + if foundFile(dir, build, source, file): + if (len(file) > 4) and (file[-4:] == ".def"): + listOfModules += [file] + listOfModules.sort() + parseModules(up, dir, build, source, listOfModules) + else: + line = "directory " + dir + " not found in either " + line += build + " or " + source + sys.stderr.write(line + "\n") + + +def displayCopyright(): + output.write("@c Copyright (C) 2000-2022 Free Software Foundation, Inc.\n") + output.write("@c This file is part of GNU Modula-2.\n") + output.write(""" +@c Permission is granted to copy, distribute and/or modify this document +@c under the terms of the GNU Free Documentation License, Version 1.2 or +@c any later version published by the Free Software Foundation. +""") + + +def collectArgs(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", help="generate progress messages", + action="store_true") + parser.add_argument("-b", "--builddir", help="set the build directory", + default=".", action="store") + parser.add_argument("-f", "--inputfile", help="set the input file", + default=None, action="store") + parser.add_argument("-o", "--outputfile", help="set the output file", + default=None, action="store") + parser.add_argument("-s", "--sourcedir", help="set the source directory", + default=".", action="store") + parser.add_argument("-t", "--texinfo", + help="generate texinfo documentation", + default=False, action="store_true") + parser.add_argument("-u", "--up", help="set the up node", + default="", action="store") + parser.add_argument("-x", "--sphinx", help="generate sphinx documentation", + default=False, action="store_true") + args = parser.parse_args() + return args + + +def handleFile(): + if args.inputfile is None: + displayCopyright() + displayMenu() + displayLibraryClass() + else: + parseDefinition(".", args.sourcedir, args.builddir, + args.inputfile, False) + + +def main(): + global args, output + args = collectArgs() + if args.outputfile is None: + output = sys.stdout + handleFile() + else: + with open(args.outputfile, "w") as output: + handleFile() + + +main() diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/mklink.c --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/mklink.c 2022-11-07 13:01:28.329424600 +0000 @@ -0,0 +1,807 @@ +/* mklink.c creates startup code and the link command line. + +Copyright (C) 2000-2022 Free Software Foundation, Inc. +Contributed by Gaius Mulley . + +This file is part of GNU Modula-2. + +GNU Modula-2 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, or (at your option) +any later version. + +GNU Modula-2 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 GNU Modula-2; see the file COPYING3. If not see +. */ + + +#include "config.h" +#include "system.h" + +#define MAX_FILE_NAME 8192 +#define MAXSTACK 4096 +#define STDIN 0 +#define STDOUT 1 +#define ENDOFILE ((char)-1) +#define ERROR(X) \ + (fprintf (stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) \ + && (fflush (stderr))) +#define DEBUG(X) \ + ((Debug) && (fprintf (stderr, "%s\n", X) && (fflush (stderr)))) + +#if !defined(TRUE) +#define TRUE (1 == 1) +#endif + +#if !defined(FALSE) +#define FALSE (1 == 0) +#endif + +typedef struct functlist +{ + char *functname; + struct functlist *next; +} functList; + +/* Prototypes. */ + +static void ParseFileLinkCommand (void); +static void ParseFileStartup (void); +static void ParseFile (char *Name); +static void ParseComments (void); +static void CopyUntilEof (void); +static void CopyUntilEol (void); +static int IsSym (char *s); +static int SymIs (char *s); +static int FindString (char *String); +static void GetNL (void); +static char GetChar (void); +static void ResetBuffer (void); +static int GetSingleChar (char *ch); +static int InRange (int Element, unsigned int Min, unsigned int Max); +static char PutChar (char ch); +static int IsSpace (char ch); +static void SkipSpaces (void); +static void SkipText (void); +static void SilentSkipSpaces (void); +static void SilentSkipText (void); +static void PushBack (char *s); +static int IsDigit (char ch); +static void GetName (char *Name); +static void OpenOutputFile (void); +static void CloseFile (void); +static void FindSource (char *Name); +static void CopyUntilEolInto (char *Buffer); +static void FindObject (char *Name); +static int IsExists (char *Name); + +/* Global variables. */ + +static char *NameOfFile = NULL; +static const char *NameOfMain = "main"; +static int StackPtr = 0; +static char Stack[MAXSTACK]; +static int CurrentFile = STDIN; +static int OutputFile; +static int LinkCommandLine = FALSE; +static int ProfilePCommand = FALSE; +static int ProfilePGCommand = FALSE; +static int ExitNeeded = TRUE; +static char *libraries = NULL; +static char *args = NULL; +static functList *head = NULL; +static functList *tail = NULL; +static int langC = FALSE; /* FALSE = C++, TRUE = C. */ + +/* addLibrary - adds libname to the list of libraries to be linked. */ + +static void +addLibrary (char *libname) +{ + if (libraries == NULL) + libraries = strdup (libname); + else + { + char *old = libraries; + char *newlib + = (char *)malloc (strlen (libname) + strlen (libraries) + 1 + 1); + strcpy (newlib, libraries); + strcat (newlib, " "); + strcat (newlib, libname); + libraries = newlib; + free (old); + } +} + +/* addGccArg - adds arg to the list of gcc arguments. */ + +static void +addGccArg (char *arg) +{ + if (args == NULL) + args = strdup (arg); + else + { + char *old = args; + char *newarg = (char *)malloc (strlen (old) + strlen (arg) + 1 + 1); + strcpy (newarg, old); + strcat (newarg, " "); + strcat (newarg, arg); + args = newarg; + free (old); + } +} + +int +main (int argc, char *argv[]) +{ + int i; + + if (argc >= 3) + { + if (strcmp (argv[1], "-l") == 0) + LinkCommandLine = TRUE; + else if (strcmp (argv[1], "-s") == 0) + LinkCommandLine = FALSE; + else + { + fprintf (stderr, "Usage: mklink (-l|-s) [--langc|--langc++] [--pg|-p] " + "[--lib library] [--main name] [--exit] --name " + "filename \n"); + fprintf (stderr, " must supply -l or -s option\n"); + exit (1); + } + ProfilePCommand = FALSE; + ProfilePGCommand = FALSE; + i = 2; + while (i < argc - 1) + { + if (strcmp (argv[i], "--langc++") == 0) + langC = FALSE; + else if (strcmp (argv[i], "--langc") == 0) + langC = TRUE; + else if (strncmp (argv[i], "-f", 2) == 0) + addGccArg (argv[i]); + else if (strcmp (argv[i], "--pg") == 0) + ProfilePGCommand = TRUE; + else if (strcmp (argv[i], "-p") == 0) + ProfilePCommand = TRUE; + else if (strcmp (argv[i], "--exit") == 0) + ExitNeeded = FALSE; + else if (strcmp (argv[i], "--lib") == 0) + { + i++; + addLibrary (argv[i]); + } + else if (strcmp (argv[i], "--main") == 0) + { + i++; + NameOfMain = argv[i]; + } + else if (strcmp (argv[i], "--name") == 0) + { + i++; + NameOfFile = argv[i]; + } + i++; + } + ParseFile (argv[i]); + } + else + { + fprintf (stderr, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib " + "library] [--main name] [--exit] --name filename " + "\n"); + exit (1); + } + if (NameOfFile == NULL) + { + fprintf (stderr, "mklink must have a --name argument\n"); + fprintf (stderr, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib " + "library] [--main name] [--exit] --name filename " + "\n"); + exit (1); + } + exit (0); +} + +/* ParseFile - parses the input file and generates the output file. */ + +static void +ParseFile (char *Name) +{ + FindSource (Name); + OpenOutputFile (); + if (LinkCommandLine) + ParseFileLinkCommand (); + else + ParseFileStartup (); + CloseFile (); +} + +/* ParseFileLinkCommand - generates the link command. */ + +static void +ParseFileLinkCommand (void) +{ + char name[MAX_FILE_NAME]; + char *s = NULL; + char *l = NULL; + char *c = NULL; + + s = getenv ("CC"); + if (s == NULL) + { + if (langC) + printf ("gcc -g "); + else + printf ("g++ -g "); + } + else + printf ("%s -g ", s); + + if (args != NULL) + printf ("%s ", args); + + l = getenv ("LDFLAGS"); + if (l != NULL) + printf ("%s ", l); + + c = getenv ("CFLAGS"); + if (c != NULL) + printf ("%s ", c); + + if (ProfilePGCommand) + printf (" -pg"); + else if (ProfilePCommand) + printf (" -p"); + + while (PutChar (GetChar ()) != (char)EOF) + { + CopyUntilEolInto (name); + if ((strlen (name) > 0) && (name[0] != '#')) + FindObject (name); + } + printf (" %s\n", libraries); +} + +/* FindObject - searches the M2PATH variable to find the object file. + If it finds the object file it prints it to stdout otherwise it + writes an error on stderr. */ + +static void +FindObject (char *Name) +{ + char m2search[4096]; + char m2path[4096]; + char name[4096]; + char exist[4096]; + int s, p; + + if (getenv ("M2PATH") == NULL) + strcpy (m2path, "."); + else + strcpy (m2path, getenv ("M2PATH")); + + snprintf (name, sizeof (name), "%s.o", Name); + p = 0; + while (m2path[p] != (char)0) + { + s = 0; + while ((m2path[p] != (char)0) && (m2path[p] != ' ')) + { + m2search[s] = m2path[p]; + s++; + p++; + } + if (m2path[p] == ' ') + p++; + m2search[s] = (char)0; + snprintf (exist, sizeof (exist), "%s/%s", m2search, name); + if (IsExists (exist)) + { + printf (" %s", exist); + return; + } + } + fprintf (stderr, "cannot find %s\n", name); +} + +/* IsExists - returns true if a file, Name, exists. It returns false + otherwise. */ + +static int +IsExists (char *Name) +{ + struct stat buf; + + return (stat (Name, &buf) == 0); +} + +/* add_function - adds a name to the list of functions, in order. */ + +void +add_function (char *name) +{ + functList *p = (functList *)malloc (sizeof (functList)); + p->functname = (char *)malloc (strlen (name) + 1); + strcpy (p->functname, name); + + if (head == NULL) + { + head = p; + tail = p; + p->next = NULL; + } + else + { + tail->next = p; + tail = p; + tail->next = NULL; + } +} + +static void +GenerateInitCalls (functList *p) +{ + while (p != NULL) + { + printf (" _M2_%s_init (argc, argv, envp);\n", p->functname); + p = p->next; + } +} + +static void +GenerateFinishCalls (functList *p) +{ + if (p->next != NULL) + GenerateFinishCalls (p->next); + printf (" _M2_%s_finish (argc, argv, envp);\n", p->functname); +} + +static void +GeneratePrototypes (functList *p) +{ + while (p != NULL) + { + if (langC) + { + printf ("extern void _M2_%s_init (int argc, char *argv[], char *envp[]);\n", + p->functname); + printf ("extern void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n", + p->functname); + } + else + { + printf ("extern \"C\" void _M2_%s_init (int argc, char *argv[], char *envp[]);\n", + p->functname); + printf ("extern \"C\" void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n", + p->functname); + } + p = p->next; + } +} + +/* ParseFileStartup - generates the startup code. */ + +static void +ParseFileStartup (void) +{ + char name[MAX_FILE_NAME]; + functList *p; + + while (PutChar (GetChar ()) != (char)EOF) + { + CopyUntilEolInto (name); + if ((strlen (name) > 0) && (strcmp (name, "mod_init") != 0) + && (name[0] != '#')) + add_function (name); + } + GeneratePrototypes (head); + printf ("extern"); + if (!langC) + printf (" \"C\""); + printf (" void _exit(int);\n"); + + printf ("\n\nint %s(int argc, char *argv[], char *envp[])\n", NameOfMain); + printf ("{\n"); + GenerateInitCalls (head); + GenerateFinishCalls (head); + if (ExitNeeded) + printf (" _exit(0);\n"); + printf (" return(0);\n"); + printf ("}\n"); +} + +/* OpenOutputFile - shut down stdout and open the new mod_init.c */ + +static void +OpenOutputFile (void) +{ + if (strcmp (NameOfFile, "-") != 0) + { + if (close (STDOUT) != 0) + { + ERROR ("Unable to close stdout"); + exit (1); + } + OutputFile = creat (NameOfFile, 0666); + if (OutputFile != STDOUT) + { + ERROR ("Expected that the file descriptor should be 1"); + } + } +} + +/* CloseFile - flush and close the file. */ + +static void +CloseFile (void) +{ +#if 0 + fflush(stdout); + if (close(STDOUT) != 0) { + ERROR("Unable to close our output file"); exit(1); + } +#endif +} + +/* CopyUntilEof - copies from the current input marker until ENDOFILE + is reached. */ + +static void +CopyUntilEof (void) +{ + char ch; + + while ((ch = GetChar ()) != ENDOFILE) + putchar (ch); +} + +/* CopyUntilEol - copies from the current input marker until '\n' is + reached. */ + +static void +CopyUntilEol (void) +{ + char ch; + + while (((ch = GetChar ()) != '\n') && (ch != (char)EOF)) + putchar (ch); + if (ch == '\n') + putchar (ch); +} + +/* CopyUntilEolInto - copies from the current input marker until '\n' + is reached into a Buffer. */ + +static void +CopyUntilEolInto (char *Buffer) +{ + char ch; + int i = 0; + + while (((ch = GetChar ()) != '\n') && (ch != (char)EOF)) + { + Buffer[i] = ch; + i++; + } + if ((ch == '\n') || (ch == (char)EOF)) + Buffer[i] = (char)0; +} + +/* IsSym - returns true if string, s, was found in the input stream. + The input stream is uneffected. */ + +static int +IsSym (char *s) +{ + int i = 0; + + while ((s[i] != (char)0) && (s[i] == PutChar (GetChar ()))) + { + GetChar (); + i++; + } + if (s[i] == (char)0) + { + PushBack (s); + /* found s in input string. */ + return (TRUE); + } + else + { + /* push back the characters we have scanned. */ + if (i > 0) + { + do + { + i--; + PutChar (s[i]); + } + while (i > 0); + } + return (FALSE); + } +} + +/* SymIs - returns true if string, s, was found in the input stream. + The token s is consumed from the input stream. */ + +static int +SymIs (char *s) +{ + int i = 0; + + while ((s[i] != (char)0) && (s[i] == PutChar (GetChar ()))) + { + GetChar (); + i++; + } + if (s[i] == (char)0) + { + /* found s in input string. */ + return (TRUE); + } + else + { + /* push back the characters we have scanned. */ + if (i > 0) + { + do + { + i--; + PutChar (s[i]); + } + while (i > 0); + } + return (FALSE); + } +} + +/* FindString - keeps on reading input until a string, String, is + matched. If end of file is reached then FALSE is returned, otherwise + TRUE is returned. */ + +static int +FindString (char *String) +{ + int StringIndex = 0; + int Found = FALSE; + int eof = FALSE; + char ch; + + while ((!Found) && (!eof)) + { + if (String[StringIndex] == (char)0) + /* must have found string. */ + Found = TRUE; + else + { + ch = GetChar (); + eof = (ch == ENDOFILE); + if (ch == String[StringIndex]) + StringIndex++; + else + StringIndex = 0; + } + } + return (Found); +} + +/* GetNL - keeps on reading input from until a new line is found. */ + +static void +GetNL (void) +{ + char ch; + + while ((ch = GetChar ()) != '\n') + putchar (ch); + putchar ('\n'); +} + +/* GetChar - returns the current character in input. */ + +static char +GetChar (void) +{ + char ch; + + if (StackPtr > 0) + { + StackPtr--; + return (Stack[StackPtr]); + } + else + { + if (GetSingleChar (&ch)) + return (ch); + else + return (ENDOFILE); + } +} + +#define MAXBUF 0x1000 +static int Pointer = 0; +static int AmountRead = 0; +static char Buffer[MAXBUF]; + +/* ResetBuffer - resets the buffer information to an initial state. */ + +static void +ResetBuffer (void) +{ + StackPtr = 0; + Pointer = 0; + AmountRead = 0; +} + +/* GetSingleChar - gets a single character from input. TRUE is + returned upon success. */ + +static int +GetSingleChar (char *ch) +{ + if (Pointer == AmountRead) + { + AmountRead = read (CurrentFile, &Buffer, MAXBUF); + if (AmountRead < 0) + AmountRead = 0; + Pointer = 0; + } + if (Pointer == AmountRead) + { + *ch = ENDOFILE; + return (FALSE); + } + else + { + *ch = Buffer[Pointer]; + Pointer++; + return (TRUE); + } +} + +/* InRange - returns true if Element is within the range Min..Max. */ + +static int +InRange (int Element, unsigned int Min, unsigned int Max) +{ + return ((Element >= Min) && (Element <= Max)); +} + +/* PutChar - pushes a character back onto input. This character is + also returned. */ + +static char +PutChar (char ch) +{ + if (StackPtr < MAXSTACK) + { + Stack[StackPtr] = ch; + StackPtr++; + } + else + { + ERROR ("Stack overflow in PutChar"); + } + return (ch); +} + +/* IsSpace - returns true if character, ch, is a space. */ + +static int +IsSpace (char ch) +{ + return ((ch == ' ') || (ch == '\t')); +} + +/* SkipSpaces - eats up spaces in input. */ + +static void +SkipSpaces (void) +{ + while (IsSpace (PutChar (GetChar ()))) + putchar (GetChar ()); +} + +/* SilentSkipSpaces - eats up spaces in input. */ + +static void +SilentSkipSpaces (void) +{ + char ch; + + while (IsSpace (PutChar (GetChar ()))) + ch = GetChar (); /* throw away character. */ +} + +/* SkipText - skips ascii text, it does not skip white spaces. */ + +static void +SkipText (void) +{ + while (!IsSpace (PutChar (GetChar ()))) + putchar (GetChar ()); +} + +/* SilentSkipText - skips ascii text, it does not skip white spaces. */ + +static void +SilentSkipText (void) +{ + char ch; + + while (!IsSpace (PutChar (GetChar ()))) + ch = GetChar (); /* throw away character. */ +} + +/* PushBack - pushes a string, backwards onto the input stack. */ + +static void +PushBack (char *s) +{ + int i; + + i = strlen (s); + while (i > 0) + { + i--; + PutChar (s[i]); + } +} + +/* IsDigit - returns true if a character, ch, is a decimal digit. */ + +static int +IsDigit (char ch) +{ + return (((ch >= '0') && (ch <= '9'))); +} + +/* GetName - returns the next name found. */ + +static void +GetName (char *Name) +{ + int i; + char ch; + + SkipSpaces (); + ch = GetChar (); + i = 0; + while (!IsSpace (ch)) + { + Name[i] = ch; + i++; + ch = GetChar (); + } + Name[i] = '\0'; +} + +/* FindSource - open source file on StdIn. */ + +static void +FindSource (char *Name) +{ + if (close (STDIN) != 0) + { + ERROR ("close on STDIN failed"); + } + CurrentFile = open (Name, O_RDONLY); + if (CurrentFile < 0) + { + perror ("failed to open file"); + exit (1); + } + if (CurrentFile != STDIN) + { + ERROR ("Expecting file descriptor value of 1"); + } +}