From patchwork Mon Oct 10 15:31:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gaius Mulley X-Patchwork-Id: 1885 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp1645313wrs; Mon, 10 Oct 2022 08:42:45 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6pANuH05B9NAdgi70b4vH6HXZDAHgLC7sxwdKlgrJHEaOkVzadmHorfpEiOuBbUWN740EB X-Received: by 2002:a17:907:75c8:b0:78d:b646:e768 with SMTP id jl8-20020a17090775c800b0078db646e768mr4921374ejc.432.1665416565481; Mon, 10 Oct 2022 08:42:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665416565; cv=none; d=google.com; s=arc-20160816; b=EiH7EZRfIuJvSUbe0SCT4e70DEvtj5SoE8vL1nFhnoeD+yqK+apYKIbSMZF2pwgsCT 6FifxNXtSXYXrF1q7M0q5nVgfp6Pg/J/M4xfmfPgzMw7gS4aQ+U6iOStL0BEcHkGQSjH 5HaNUIATbncXWWEd3oc1Vqjs/5fl/l7qhUfwCxIHFdh34N42i//aN9lXV6iohwVRCL6k 50aDukcEqUtea6IeU7LbKD6PDOAAfGDYyzZwEImpBDgvy9Drrw1r1N2sOWswsKo8r+ZZ 83GQglH+3nUgon/WICtl8Wk4PR/VRcilcOl9nFNYC/urrued9JJMHabZWHqZWi5lAqE1 UvMA== 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:date:message-id:to :subject:dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=7yQ7bvhN2RMdLFoRYbfda1ZZF3o9BqQCeqPqyyqawpM=; b=Zuhkqr0Y6sEQRqvlBvaanPHX5tmFYxonCtZOVPNtNt52mW0xEbn2GWZoRr8baHSk+W OhbQHPryf12mwT36j5fJtPt70yZiA2oYOFUfGJKWb+odlfN5zr2zrR0rK/NNMFLS79ou vW9iXdlNfgCj3W7xTUARMFTaoVoY3eXLswKSz+YnBIfwTnFS7RinTFZ3tHfQ85BfqlwN LKiUb7jMbDWduqYaJsb/vUv/nxjOIG0KtOWzQ22S1p9eebYyIuQg5myOPQk62N4WbkZJ SdF9haG17ZC0r/drtbn+0pok+3iOKIjaYUJLHNtntwY+xxm+SfW/JXg+KEdL09XIr5WF haLA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=A1618ioD; 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 (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id s3-20020a05640217c300b00443e3fe60a0si8913010edy.622.2022.10.10.08.42.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Oct 2022 08:42:45 -0700 (PDT) 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=A1618ioD; 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 CB4DF3952527 for ; Mon, 10 Oct 2022 15:38:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CB4DF3952527 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1665416334; bh=7yQ7bvhN2RMdLFoRYbfda1ZZF3o9BqQCeqPqyyqawpM=; h=Subject:To:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=A1618ioDtJ8xF5Kg8K1yKyOV9ba47w74yatZrV4Y2Yi8Z/TMsA0DItCU8qoziO6/3 lKp5RnQnwbaHNuBYo37a+sm7qYoW0XA01Prijb6Y2YN94WDgjE18CBwUBHwqSZwZhc 8dPUvQZDFRZJMXcf+scBGFte0gKmdhcEFdUIfh6Y= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by sourceware.org (Postfix) with ESMTPS id 5C8A5383FBB8 for ; Mon, 10 Oct 2022 15:31:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5C8A5383FBB8 Received: by mail-wm1-x333.google.com with SMTP id az22-20020a05600c601600b003c6b72797fdso1586932wmb.5 for ; Mon, 10 Oct 2022 08:31:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=date:message-id:to:subject:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7yQ7bvhN2RMdLFoRYbfda1ZZF3o9BqQCeqPqyyqawpM=; b=iUReM1qWHL7vRLkTCFeCrtRESVfka3esd6cLkE9eFu2s/6Qzz+vxIsoeE1qmhfBE2s BYxmL8YRmD8NPLWNI9iVu1vKyQhaHTadZNBZqc3ACEreVIvuBE3BmIvm9cv71R8Fc6BL n0LDQxvRkxSMyOS2X8155lHj5FHpVBK9M6btNnZGV7IoV63EgplXURVB23IQKVthFpmr yuDVp1Hc/upuON3FptDs9HCz1fsk6vccxDjJLLZhgh7MXyD9V92Q6RqoWwkwUZKGOB92 n0PAykmLEdNSkn4WB7F0OyqFNsH0yWgODLd6XKWpeuHv4JLlVe6/+5+SwmbLLfwVNVRI Znyg== X-Gm-Message-State: ACrzQf0SLFdY7H2c4G+SyUSU5rWoD5bzbK9SQhKrGabvQFORhVRe+qi5 1Lun0nsAG88ockNaiu8e5puVLVbAb7s= X-Received: by 2002:a05:600c:3ce:b0:3c6:bf0b:5467 with SMTP id z14-20020a05600c03ce00b003c6bf0b5467mr2088671wmd.130.1665415898346; Mon, 10 Oct 2022 08:31:38 -0700 (PDT) Received: from lancelot ([195.147.220.46]) by smtp.gmail.com with ESMTPSA id l4-20020a7bc444000000b003a2e92edeccsm16489752wmi.46.2022.10.10.08.31.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Oct 2022 08:31:37 -0700 (PDT) X-Google-Original-From: Gaius Mulley Received: from gaius by lancelot with local (Exim 4.94.2) (envelope-from ) id 1ohukX-00Bm41-MC for gcc-patches@gcc.gnu.org; Mon, 10 Oct 2022 16:31:25 +0100 Subject: [PATCH] 16/19 modula2 front end: bootstrap and documentation tools To: X-Mailer: mail (GNU Mailutils 3.10) Message-Id: Date: Mon, 10 Oct 2022 16:31:25 +0100 X-Spam-Status: No, score=-0.8 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, URI_LONG_REPEAT autolearn=no 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?1746315840666651898?= X-GMAIL-MSGID: =?utf-8?q?1746315840666651898?= This patch set contains the bootstrap linking tool as well as python3 scripts to automatically generate texi libraries section of the gm2 documentation. In the fullness of time this will be changed to emit sphinx. ------8<----------8<----------8<----------8<----------8<----------8<---- 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-10-07 20:21:18.682097332 +0100 @@ -0,0 +1,184 @@ +#!/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, sys + +maxLineLength = 60 + + +# +# visitDir - call func for each file below, dir, matching extension, ext. +# + +def visitDir (dir, ext, func): + listOfFiles = os.listdir(dir) + listOfFiles.sort() + for file in listOfFiles: + if os.path.isfile(os.path.join(dir, file)): + l = len(ext) + if (len(file)>l) and (file[-l:] == ext): + func(os.path.join(dir, file)) + elif os.path.isdir(os.path.join(dir, file)): + visitDir(os.path.join(dir, file), ext, func) + +# +# isYear - returns True if, year, is legal. +# + +def isYear (year): + if len(year)==5: + year = year[:-1] + for c in year: + if not c.isdigit(): + return False + return True + + +# +# handleCopyright - +# + +def handleCopyright (outfile, lines, n, leader1, leader2): + global maxLineLength + i = lines[n] + c = i.find('Copyright (C) ')+len('Copyright (C)') + 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 + +# +# handleHeader - reads in the header of a file and inserts +# a line break around the Copyright dates. +# + +def handleHeader (file, leader1, leader2): + print("------------------------------") + l = open(file, 'r').readlines() + if len(l)>20: + outfile = open('tmptidy', 'w') + n = 0 + for i in l: + if i.find('Copyright (C)')>=0: + outfile, n = handleCopyright(outfile, l, n, leader1, leader2) + outfile.writelines(l[n:]) + outfile.close() + print("-> mv tmptidy", file) + command = "mv tmptidy %s" % file + os.system(command) + return + else: + outfile.write(l[n]) + n += 1 + outfile.close() + sys.stdout.write("%s:1:1 needs a Copyright notice..\n" % file) + + +# +# bashTidy - tidy up dates using '#' comment +# + +def bashTidy (file): + handleHeader(file, '#', ' ') + +# +# cTidy - tidy up dates using '/* */' comments +# + +def cTidy (file): + handleHeader(file, ' ', '*') + +# +# m2Tidy - tidy up dates using '(* *)' comments +# + +def m2Tidy (file): + handleHeader(file, ' ', ' ') + +# +# main - for each file extension call the appropriate tidy +# routine. +# + +def main (): + 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-10-07 20:21:18.682097332 +0100 @@ -0,0 +1,599 @@ +#!/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 sys +import os +import glob +import sys, getopt, string +import datetime + +forceGPL3x, forceGPL3 = False, False +doModify, verbose = True, False, +multiFilemode, updateAll, forceCheck = False, False, False + +summaryGiven, contributedBy, outputName = "", "", "-" +errorCount = 0 +startDir = "." +seenFiles = [] + + +# +# printf - keeps C programmers happy :-) +# + +def printf (fmt, *args): + print(str (fmt) % args, end=' ') + +# +# error - issue an error message. +# + +def error (fmt, *args): + 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] + + +# +# analyseComment - +# + +def analyseComment (text, f): + start_date, end_date, contribution, summary, lic = None, None, None, None, None + if text.find ("Copyright ISO/IEC") > 0: + lic = "BSISO" + now = datetime.datetime.now () + for d in range (1984, now.year+1): + if text.find (str (d)) > 0: + if start_date == None: + start_date = str (d) + end_date = str (d) + return start_date, end_date, "", "", lic + elif text.find ("Copyright (C)") > 0: + if text.find ("GNU General Public License") > 0: + lic = "GPL" + elif text.find ("GNU Lesser General") > 0: + lic = "LGPL" + if text.find ("version 2.1") > 0: + lic += "v2.1" + elif text.find ("version 2") > 0: + lic += "v2" + elif text.find ("version 3") > 0: + lic += "v3" + if text.find ("GCC Runtime Library Exception") > 0: + lic += "x" + now = datetime.datetime.now () + for d in range (1984, now.year+1): + if text.find (str (d)) > 0: + if start_date == None: + start_date = str (d) + end_date = str (d) + if text.find ("ontributed by") > 0: + i = text.find ("ontributed by") + i += len ("ontributed 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 + + +# +# analyseHeader - +# + +def analyseHeader (f, start, end): + text = "" + if end == None: + for count, l in enumerate (open (f, "r").readlines ()): + parts = l.split (start) + if len (parts) > 1: + line = start.join (parts[1:]) + line = line.rstrip () + line = line.lstrip () + text += " " + text += line + elif (l.rstrip () != "") and (len (parts[0]) > 0): + return analyseComment (text, f), count + else: + inComment = False + for count, l in enumerate (open (f, "r").readlines ()): + while l != "": + l = l.strip () + l = l.rstrip () + if inComment: + text += " " + pos = l.find (end) + if pos >= 0: + text += l[:pos] + l = l[pos:] + inComment = False + else: + text += l + l = "" + else: + pos = l.find (start) + if (pos >= 0) and (len (l) > len (start)): + before = l[:pos] + before = before.rstrip () + before = before.lstrip () + if before != "": + return analyseComment (text, f), count + l = l[pos + len (start):] + inComment = True + elif (l != "") and (l == end): + l = "" + else: + return analyseComment (text, f), count + return [None, None, None, None, None], 0 + + +# +# addStop - add a full stop to a sentance. +# + +def addStop (sentence): + 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 = { "GPLv3":GPLv3, + "GPLv3x":GPLv3x, + "LGPLv3":LGPLv3, + "LGPLv2.1":LGPLv3, + "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 != None: + fo.write (magic) + fo.write ("\n") + text = templates[lic] % (summary, dates, contribution) + text = text.rstrip () + if end == 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 == 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): + l = open (f, "r").readlines ()[lines:] + text = "".join (l) + 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 () + + +# +# handleHeader - keep reading lines of file, f, looking for start, end +# sequences and comments inside. The comments are checked +# for: date, contribution, summary +# + +def handleHeader (f, magic, start, end): + global date, contribution, summary, doModify, forceCheck, errorCount + + errorCount = 0 + [start_date, end_date, contribution, summary, lic], lines = analyseHeader (f, start, end) + if lic == None: + error ("%s:1:no GPL found at the top of the file\n", f) + else: + if verbose: + printf ("copyright: %s\n", lic) + if (start_date != None) and (end_date != None): + if start_date == end_date: + printf ("dates = %s\n", start_date) + else: + printf ("dates = %s-%s\n", start_date, end_date) + if summary != None: + printf ("summary: %s\n", summary) + if contribution != None: + printf ("contribution: %s\n", contribution) + if start_date == None: + error ("%s:1:no date found in the GPL at the top of the file\n", f) + if contribution == None: + if contributedBy == "": + error ("%s:1:no contribution found in the GPL at the top of the file\n", f) + else: + contribution = contributedBy + if summary == None: + if summaryGiven == "": + error ("%s:1:no single line summary found in the GPL at the top of the file\n", f) + else: + summary = summaryGiven + if errorCount == 0: + now = datetime.datetime.now () + if doModify: + if lic == "BSISO": + # don't change the BS ISO license! + pass + elif forceGPL3x: + lic = "GPLv3x" + elif forceGPL3: + lic = "GPLv3" + rewriteFile (f, magic, start, end, start_date, str (now.year), contribution, summary, lic, lines) + elif forceCheck: + print(f, "suppressing change as requested", start_date, end_date, lic) + else: + printf ("too many errors, no modifications will occur\n") + + +# +# bashTidy - tidy up dates using '#' comment +# + +def bashTidy (f): + handleHeader (f, "#!/bin/bash", "#", None) + + +# +# pythonTidy - tidy up dates using '#' comment +# + +def pythonTidy (f): + handleHeader (f, "#!/usr/bin/env python3", '#', None) + + +# +# bnfTidy - tidy up dates using '--' comment +# + +def bnfTidy (f): + handleHeader (f, None, '--', None) + + +# +# cTidy - tidy up dates using '/* */' comments +# + +def cTidy (f): + handleHeader (f, None, '/*', '*/') + +# +# m2Tidy - tidy up dates using '(* *)' comments +# + +def m2Tidy (f): + handleHeader (f, None, '(*', '*)') + +# +# inTidy - tidy up dates using '#' as a comment and check the first line for magic number. +# + +def inTidy (f): + first = open (f, "r").readlines ()[0] + if (len (first) > 0) and (first[:2] == "#!"): + # magic number found, use this + handleHeader (f, first, "#", None) + else: + handleHeader (f, None, "#", None) + + +# +# doVisit - +# + +def doVisit (args, dirname, names): + global outputName + func, extension = args + for f in names: + if len (f) > len (extension) and f[-len (extension):] == extension: + # print os.path.join (dirname, f) + outputName = f + func (os.path.join (dirname, f)) + + +# +# visitDir - visit +# + +def visitDir (startDir, extension, func): + global outputName, seenFiles + # os.walk (startDir, doVisit, [func, extension]) + for dirName, subdirList, fileList in os.walk(startDir): + for fname in fileList: + if (len (fname) > len (extension)) and (fname[-len(extension):] == extension): + fullpath = os.path.join (dirName, fname) + outputName = fullpath + # printf ("outputName = %s\n", outputName) + 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] + +# +# findFiles - for each file extension call the appropriate tidy +# routine. +# + +def findFiles (): + visitDir (startDir, '.h.in', cTidy) + visitDir (startDir, '.in', inTidy) + visitDir (startDir, '.sh', inTidy) + visitDir (startDir, '.py', pythonTidy) + visitDir (startDir, '.c', cTidy) + visitDir (startDir, '.h', cTidy) + visitDir (startDir, '.cc', cTidy) + visitDir (startDir, '.def', m2Tidy) + visitDir (startDir, '.mod', m2Tidy) + visitDir (startDir, '.bnf', bnfTidy) + + +# +# usage - output very brief usage instructions. +# + +def usage (code = 0): + print("boilerplate [-c contributionstring] [ -s summarystring ] [-d] [-v] [-g] [-x] [-o outputfile] inputfile.c") + print(" -o outputfile (this must be before the final inputfile on the command line).") + print(" -c a string which will be used as the contribution line.") + print(" -s a string which will be used as the summary line.") + print(" -f force a check to insist that the contribution, summary and GPL exists.") + print(" -g change to GPLv3.") + print(" -x change to GPLv3 with GCC runtime extension.") + print(" -r directory recusively scan directory for known file extensions (.def, .mod, .c, .h, .py, .in, .sh).") + print(" -u update all dates.") + print(" -v verbose.") + print(" -N do not modify any file") + os.sys.exit (code) + + +# +# handleArguments - check the legal arguments. +# + +def handleArguments (): + global multiFilemode, contributedBy, updateAll, forceCheck, outputName, verbose, startDir, doModify, forceGPL3, forceGPL3x, summaryGiven + try: + optlist, l = getopt.getopt (sys.argv[1:],':c:dfgho:r:s:uvxN') + except getopt.GetoptError: + usage (1) + for opt in optlist: + if opt[0] == '-c': + contributedBy = opt[1] + if opt[0] == '-s': + summaryGiven = opt[1] + if opt[0] == '-d': + debugging = True + if opt[0] == '-f': + forceCheck = True + if opt[0] == '-g': + forceGPL3 = True + if opt[0] == '-x': + forceGPL3x = True + if opt[0] == '-h': + usage () + if opt[0] == '-r': + multiFilemode = True + startDir = opt[1] + if opt[0] == '-o': + outputName = opt[1] + if opt[0] == '-u': + updateAll = True + if opt[0] == '-v': + verbose = True + if opt[0] == '-N': + doModify = False + if l == []: + return None + return l[0] + + +# +# hasExt - return True if, name, ends with, ext. +# + +def hasExt (name, ext): + if len (name) > len (ext): + return name[-len (ext):] == ext + return False + + +# +# singleFile - scan the single file for a GPL boilerplate which +# has a GPL, contribution field and a summary heading. +# + +def singleFile (i): + if hasExt (i, ".def") or hasExt (i, ".mod"): + m2Tidy (i) + elif hasExt (i, ".h") or hasExt (i, ".c") or hasExt (i, ".cc"): + cTidy (i) + elif hasExt (i, ".in"): + inTidy (i) + elif hasExt (i, ".sh"): + inTidy (i) # uses magic number for actual sh/bash + elif hasExt (i, ".py"): + pythonTidy (i) + + +# +# main - handleArguments and then find source files. +# + +def main (): + i = handleArguments () + if multiFilemode: + findFiles () + elif i == None: + print("an input file must be specified on the command line") + usage (1) + else: + singleFile (i) + 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-10-07 20:21:18.682097332 +0100 @@ -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-10-07 20:21:18.682097332 +0100 @@ -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-10-07 20:21:18.682097332 +0100 @@ -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-10-07 20:21:18.682097332 +0100 @@ -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/mklink.c --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/mklink.c 2022-10-07 20:21:18.682097332 +0100 @@ -0,0 +1,810 @@ +/* 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 defined(XENIX) + name[10] = (char)0; /* truncate object file name. */ +#endif + 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"); + } +} diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/def2texi.py --- /dev/null 2022-08-24 16:22:16.888000070 +0100 +++ gcc-git-devel-modula2/gcc/m2/tools-src/def2texi.py 2022-10-07 20:21:18.682097332 +0100 @@ -0,0 +1,423 @@ +#!/usr/bin/env python3 + +# def2texi.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 sys +import os +import glob +import getopt + +libraryClassifications = [['gm2-libs','Base libraries', + 'Basic M2F compatible libraries'], + ['gm2-libs-pim','PIM and Logitech 3.0 Compatible', + 'PIM and Logitech 3.0 compatible libraries'], + ['gm2-libs-coroutines','PIM coroutine support', + 'PIM compatible process support'], + ['gm2-libs-iso','M2 ISO Libraries', + 'ISO defined libraries']] + +def initState (): + global inVar, inType, inConst + inVar, inType, inConst = False, False, False + + +# +# displayLibraryClass - displays a node for a library directory and invokes +# a routine to summarize each module +# + +def displayLibraryClass(): + global buildDir, up + previous = "" + + next=libraryClassifications[1][1] + i = 0 + l = libraryClassifications[i] + + while True: + print("@node " + l[1] + ", " + next + ", " + previous + ", " + up) + print("@section " + l[1]) + print("") + displayModules(l[1], l[0], buildDir, sourceDir) + print("") + print("@c ---------------------------------------------------------------------") + previous = l[1] + i += 1 + if i == len(libraryClassifications): + break + l = libraryClassifications[i] + if i+1 == len(libraryClassifications): + next = "" + else: + next = libraryClassifications[i+1][1] + +# +# displayMenu - displays the top level menu for library documentation +# + +def displayMenu(): + print("@menu") + for l in libraryClassifications: + print("* " + l[1] + "::" + l[2]) + print("@end menu") + + print("\n") + print("@c =====================================================================") + print("\n") + + +# +# removeInitialComments - removes any (* *) at the top of the definition module +# + +def removeInitialComments (file, line): + while (str.find(line, "*)") == -1): + line = file.readline() + +# +# removeFields - removes Author/Date/Last edit/SYSTEM/Revision fields from a comment within the start +# of a definition module +# + +def removeFields (file, line): + while (str.find(line, "*)") == -1): + if (str.find(line, "Author") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "Last edit") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "LastEdit") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "Last update") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "Date") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "Title") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "Revision") != -1) and (str.find(line, ":") != -1): + line = file.readline() + elif (str.find(line, "System") != -1) and (str.find(line, ":") != -1) and (str.find(line, "Description:") == -1): + line = file.readline() + elif (str.find(line, "SYSTEM") != -1) and (str.find(line, ":") != -1) and (str.find(line, "Description:") == -1): + line = file.readline() + else: + print(str.replace(str.replace(str.rstrip(line), + "{", "@{"), "}", "@}")) + line = file.readline() + print(str.rstrip(line)) + + +# +# checkIndex +# + +def checkIndex (line): + 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: + print("@findex " + word + " (var)") + elif len(word)>0: + var = str.split(word, ':') + if len(var)>0: + print("@findex " + var[0] + " (var)") + + if inType: + words = str.lstrip(line) + if str.find(words, '=') != -1: + word = str.split(words, "=") + if (len(word[0])>0) and (word[0][0] != '_'): + print("@findex " + str.rstrip(word[0]) + " (type)") + else: + word = str.split(words) + if (len(word)>1) and (word[1] == ';'): + # hidden type + if (len(word[0])>0) and (word[0][0] != '_'): + print("@findex " + str.rstrip(word[0]) + " (type)") + + 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: + print("@findex " + var[0] + " (const)") + + if procedure != "": + name = str.split(procedure, "(") + if name[0] != "": + proc = name[0] + if proc[-1] == ";": + proc = proc[:-1] + if proc != "": + print("@findex " + proc) + + +# +# parseDefinition +# + +def parseDefinition (dir, source, build, file, needPage): + print("") + f = open(findFile(dir, build, source, file), 'r') + initState() + line = f.readline() +# while (str.find(line, "(*") != -1): + while (str.find(line, "(*") != -1): + removeInitialComments(f, line) + line = f.readline() + + while (str.find(line, "DEFINITION") == -1): + line = f.readline() + + print("@example") + print(str.rstrip(line)) + line = f.readline() + if len(str.rstrip(line)) == 0: + print(str.replace(str.replace(str.rstrip(line), + "{", "@{"), "}", "@}")) + line = f.readline() + if (str.find(line, "(*") != -1): + removeFields(f, line) + else: + print(str.rstrip(line)) + else: + print(str.rstrip(line)) + + line = f.readline() + while line: + line = str.rstrip(line) + checkIndex(line) + print(str.replace(str.replace(line, "{", "@{"), "}", "@}")) + line = f.readline() + print("@end example") + if needPage: + print("@page") + f.close() + +def parseModules (up, dir, build, source, listOfModules): + previous = "" + i = 0 + if len(listOfModules)>1: + next = dir + "/" + listOfModules[1][:-4] + else: + next = "" + + while i4) and (file[-4:] == '.def'): + print("* " + dir + "/" + file[:-4] + "::" + file) + print("@end menu") + print("\n") + + +# +# checkDirectory - returns True if dir exists in either build or source. +# + +def checkDirectory (dir, build, 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 + + +# +# foundFile - return True if file is found in build/dir/file or source/dir/file. +# + +def foundFile (dir, build, source, 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 + + +# +# findFile - return the path to file searching in build/dir/file first then source/dir/file. +# + +def findFile (dir, build, source, 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 + print("file cannot be found in either " + name1 + " or " + name2) + os.sys.exit(1) + + +# +# displayModules - walks though the files in dir and parses +# definition modules and includes README.texi +# + +def displayModules(up, dir, build, source): + 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: + print("directory " + dir + " not found in either " + build + " or " + source) + + +def displayCopyright (): + print("@c Copyright (C) 2000-2022 Free Software Foundation, Inc.") + print("@c This file is part of GNU Modula-2.") + print(""" +@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 Usage(): + print("def2texi.py [-h][-bbuilddir][-uupnode][-ffilename]") + +def collectArgs(): + buildDir="." + sourceDir="." + filename="" + up="" + try: + optlist, list = getopt.getopt(sys.argv[1:],':hb:f:s:u:') + except getopt.GetoptError: + Usage() + os.sys.exit(1) + for opt in optlist: + if opt[0] == '-h': + Usage() + if opt[0] == '-b': + buildDir = opt[1] + if opt[0] == '-f': + filename = opt[1] + if opt[0] == '-s': + sourceDir = opt[1] + if opt[0] == '-u': + up = opt[1] + return buildDir, sourceDir, filename, up + + +buildDir, sourceDir, filename, up = collectArgs() + +if filename == "": + displayCopyright() + displayMenu() + displayLibraryClass() +else: + parseDefinition('.', sourceDir, buildDir, filename, False) 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"); + } +}