From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id CCAAF3857BB5 for ; Thu, 13 Oct 2022 09:12:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CCAAF3857BB5 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id CE67921D21; Thu, 13 Oct 2022 09:12:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1665652336; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8dxmagt9bZwKPpoLUZNMe3HNdO2VeoxRASIKsYdRUJw=; b=XP1yIdDgQPOeX1TbS/1CPCUxtoUC4gTgHOgTmUJxtwSrNTOMaZ/x1iMSWQqJnF9AXcdk5w TtN7NFuGOk1R1XV8KZksY4BSiXJ9yhf8J0nc1Dp1NKNYcVzt2HDW2vnz+PuxALWARJE+f9 S1gVYklph3gSHkzqYEgl8zcFWeFlMUA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1665652336; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8dxmagt9bZwKPpoLUZNMe3HNdO2VeoxRASIKsYdRUJw=; b=ZgWmxP7upm3eH69UxVZ2BqgKt3Oky1ZsdnML5UnpEwqsCTDZGQoUcjdnh5KsksZPNCLO1m ogOEvUman5/uI1DA== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id A0F9A13AAA; Thu, 13 Oct 2022 09:12:16 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id hss6JnDWR2P5BQAAMHmgww (envelope-from ); Thu, 13 Oct 2022 09:12:16 +0000 Message-ID: <11f42175-8e23-5da3-6a13-6172039bfca2@suse.cz> Date: Thu, 13 Oct 2022 11:12:16 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.1 Subject: Re: [PATCH] 16/19 modula2 front end: bootstrap and documentation tools Content-Language: en-US To: Gaius Mulley , gcc-patches@gcc.gnu.org References: From: =?UTF-8?Q?Martin_Li=c5=a1ka?= In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,NICE_REPLY_A,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_SOFTFAIL,TXREP,URI_LONG_REPEAT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 10/10/22 17:31, Gaius Mulley via Gcc-patches wrote: > > Hi! > 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. Yep, looking forward to it. I'm going to write an email with Sphinx transition schedule once Sphinx 5.3 gets released (should happen during the upcoming weekend). I have general comments about the Python scripts: 1) please follow the Python coding style and not the GCC one (I'm going to document it in https://gcc.gnu.org/codingconventions.html under a new Python section). The easiest approach is using flake8 and the following plugins: python3-flake8, python3-flake8-builtins, python3-flake8-bugbear, python3-flake8-import-order, python3-flake8-quotes plus, you might want to come up with a setup.cfg like we have in: ./maintainer-scripts/setup.cfg > > > ------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)) please use pathlib.Path(...).stem > + 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 = "" Please unify "" and '', you only apostrophes. > + 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') use 'with open(...) as outfile:' https://docs.python.org/3/reference/compound_stmts.html#the-with-statement > + 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) shutil.move > + return > + else: > + outfile.write(l[n]) > + n += 1 > + outfile.close() ... will be closed automatically by 'with' statement. > + sys.stdout.write("%s:1:1 needs a Copyright notice..\n" % file) > + > + > +# > +# bashTidy - tidy up dates using '#' comment > +# > + > +def bashTidy (file): Better putting comments here in function body. > + 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: better 'Copyright (C)' in text, similarly at other places .. > + 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 () line = line.strip() > + 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 ()): 'r' is default > + while l != "": > + l = l.strip () > + l = l.rstrip () > + if inComment: > + text += " " > + pos = l.find (end) better use https://docs.python.org/3/library/stdtypes.html?highlight=partition#str.partition > + 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) f-string format might be better, but that's just a hint: https://docs.python.org/3/reference/lexical_analysis.html#f-strings > + 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: I prefer 'if not start_date' (simiarly at other places). > + 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): Path(...).stem again would be better. > + 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) https://docs.python.org/3/library/argparse.html would be much better, you get arguments parsing for free. > + > + > +# > +# 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] ^^^ this will be done automatically. Hope it's usefull. Thanks, Martin > + > + > +# > +# 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 i + print("@node " + dir + "/" + listOfModules[i][:-4] + ", " + next + ", " + previous + ", " + up) > + print("@subsection " + dir + "/" + listOfModules[i][:-4]) > + parseDefinition(dir, source, build, listOfModules[i], True) > + print("\n") > + previous = dir + "/" + listOfModules[i][:-4] > + i = i + 1 > + if i+1 + next = dir + "/" + listOfModules[i+1][:-4] > + else: > + next = "" > + > + > +# > +# doCat - displays the contents of file, name, to stdout > +# > + > +def doCat (name): > + file = open(name, 'r') > + line = file.readline() > + while line: > + print(str.rstrip(line)) > + line = file.readline() > + file.close() > + > + > +# > +# moduleMenu - generates a simple menu for all definition modules > +# in dir > +# > + > +def moduleMenu (dir, build, source): > + print("@menu") > + 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'): > + 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)