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)