From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id 445F83858D26 for ; Mon, 7 Nov 2022 13:47:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 445F83858D26 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass 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 0A8CE22562; Mon, 7 Nov 2022 13:47:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1667828823; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=V2bZNbDsTpyqLuBWafPwE84Kb1DijzUzl8rC18fxhZs=; b=mGEqsHGULHRmJzEkiwDqCh/lpRor5ntYXNQoWQ4W5+o8mkqrtHqhjSwcPomnZYSTywJNIg FxW1TARHxeRPMCsUkip8Fll8TSJEw6k6H2bxzI5yzraRHLU5+jrQZ12FYBJY04otlic/hz TfR8Usasdp4h+vPfVf4KUOAUbIoVpeE= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1667828823; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=V2bZNbDsTpyqLuBWafPwE84Kb1DijzUzl8rC18fxhZs=; b=DRPWOGGbVr/a0iZfz32MgRDlCHTLT8QymEM2AtpHamosg98Ud796dNK2vcaea7kFOI5cAb hXRw/0c6n/nlXGBA== 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 D6D3513494; Mon, 7 Nov 2022 13:47:02 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id ezBNM1YMaWN/ZQAAMHmgww (envelope-from ); Mon, 07 Nov 2022 13:47:02 +0000 Message-ID: <50b276a7-3a18-d405-b672-eecb5067f5de@suse.cz> Date: Mon, 7 Nov 2022 14:47:02 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.1 Subject: Re: [PATCH v2 16/19] modula2 front end: bootstrap and documentation tools To: Gaius Mulley Cc: gcc-patches@gcc.gnu.org References: <11f42175-8e23-5da3-6a13-6172039bfca2@suse.cz> <87k052ppvq.fsf@debian> <87r0yesygv.fsf_-_@debian> Content-Language: en-US From: =?UTF-8?Q?Martin_Li=c5=a1ka?= In-Reply-To: <87r0yesygv.fsf_-_@debian> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-5.9 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 11/7/22 14:09, Gaius Mulley wrote: > > Hi Martin, > > here is the revised patch having applied all previous recommendations: > > https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603436.html Hi. > > Is this ok now? Thanks for the improvement suggestions (argparse > results in fewer lines of code :-) Thanks, much better, however some comments are still not addressed: 1) I would prefer using ' instead of ": $ flake8 ./gcc/m2/tools-src/tidydates.py ... ./gcc/m2/tools-src/tidydates.py:124:30: Q000 Double quotes found but single quotes preferred ./gcc/m2/tools-src/tidydates.py:127:27: Q000 Double quotes found but single quotes preferred ./gcc/m2/tools-src/tidydates.py:132:27: Q000 Double quotes found but single quotes preferred ./gcc/m2/tools-src/tidydates.py:133:33: Q000 Double quotes found but single quotes preferred ./gcc/m2/tools-src/tidydates.py:138:26: Q000 Double quotes found but single quotes preferred ./gcc/m2/tools-src/tidydates.py:143:28: Q000 Double quotes found but single quotes preferred 2) Python-names would be nicer: def writeTemplate(fo, magic, start, end, dates, contribution, summary, lic): def write_template(...) 3) def hasExt(name, ext) - please use Path from pathlib 4) while (str.find(line, "(*") != -1): '(*' in line ? Similarly elsewhere. 5) str.find(line, ...) Use rather directly: line.find(...) 6) please use flake8: https://gcc.gnu.org/codingconventions.html#python Thanks, Martin P.S. I'm going to merge Sphinx branch this Wednesday, so then we should port your conversion scripts to emit .rst instead of .texi. > > regards, > Gaius > > > ------8<----------8<----------8<----------8<----------8<----------8<---- > diff -ruw /dev/null gcc-git-devel-modula2/mliska@suse.cz > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/tidydates.py > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/tidydates.py 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,166 @@ > +#!/usr/bin/env python3 > + > +# utility to tidy dates and detect lack of copyright. > + > +# Copyright (C) 2016-2022 Free Software Foundation, Inc. > +# > +# This file is part of GNU Modula-2. > +# > +# GNU Modula-2 is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3, or (at your option) > +# any later version. > +# > +# GNU Modula-2 is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with GNU Modula-2; see the file COPYING. If not, write to the > +# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA > +# 02110-1301, USA. > + > +import os > +import sys > +import pathlib > +import shutil > + > +maxLineLength = 60 > + > +COPYRIGHT = "Copyright (C)" > + > + > +def visitDir(directory, ext, func): > + # visitDir - call func for each file below, dir, matching extension, ext. > + listOfFiles = os.listdir(directory) > + listOfFiles.sort() > + for filename in listOfFiles: > + path = pathlib.PurePath(filename) > + full = os.path.join(directory, filename) > + if path.is_file(full): > + if path.suffix == ext: > + func(full) > + elif path.is_dir(full): > + visitDir(full, ext, func) > + > + > +def isYear(year): > + # isYear - returns True if, year, is legal. > + if len(year) == 5: > + year = year[:-1] > + for c in year: > + if not c.isdigit(): > + return False > + return True > + > + > +def handleCopyright(outfile, lines, n, leader1, leader2): > + # handleCopyright look for Copyright in the comment. > + global maxLineLength > + i = lines[n] > + c = i.find(COPYRIGHT)+len(COPYRIGHT) > + outfile.write(i[:c]) > + d = i[c:].split() > + start = c > + seenDate = True > + years = [] > + while seenDate: > + if d == []: > + n += 1 > + i = lines[n] > + d = i[2:].split() > + else: > + e = d[0] > + punctuation = "" > + if len(d) == 1: > + d = [] > + else: > + d = d[1:] > + if c > maxLineLength: > + outfile.write("\n") > + outfile.write(leader1) > + outfile.write(leader2) > + outfile.write(" "*(start-2)) > + c = start > + if isYear(e): > + if (e[-1] == ".") or (e[-1] == ","): > + punctuation = e[-1] > + e = e[:-1] > + else: > + punctuation = "" > + else: > + seenDate = False > + if seenDate: > + if not (e in years): > + c += len(e) + len(punctuation) > + outfile.write(" ") > + outfile.write(e) > + outfile.write(punctuation) > + years += [e] > + else: > + if start < c: > + outfile.write("\n") > + outfile.write(leader1) > + outfile.write(leader2) > + outfile.write(" "*(start-2)) > + > + outfile.write(" ") > + outfile.write(e) > + outfile.write(punctuation) > + for w in d: > + outfile.write(" ") > + outfile.write(w) > + outfile.write("\n") > + return outfile, n+1 > + > + > +def handleHeader(filename, leader1, leader2): > + # handleHeader reads in the header of a file and inserts > + # a line break around the Copyright dates. > + print("------------------------------") > + lines = open(filename, "r").readlines() > + if len(lines) > 20: > + with open("tmptidy", "w") as outfile: > + n = 0 > + for i in lines: > + if i.find("Copyright (C)") >= 0: > + outfile, n = handleCopyright(outfile, lines, > + n, leader1, leader2) > + outfile.writelines(lines[n:]) > + outfile.close() > + print("-> mv tmptidy", filename) > + shutil.move("tmptidy", filename) > + return > + else: > + outfile.write(lines[n]) > + n += 1 > + sys.stdout.write("%s:1:1 needs a Copyright notice..\n" % filename) > + > + > +def bashTidy(filename): > + # bashTidy - tidy up dates using "#" comment > + handleHeader(filename, "#", " ") > + > + > +def cTidy(filename): > + # cTidy - tidy up dates using "/* */" comments > + handleHeader(filename, " ", "*") > + > + > +def m2Tidy(filename): > + # m2Tidy - tidy up dates using "(* *)" comments > + handleHeader(filename, " ", " ") > + > + > +def main(): > + # main - for each file extension call the appropriate tidy routine. > + visitDir(".", ".in", bashTidy) > + visitDir(".", ".py", bashTidy) > + visitDir(".", ".c", cTidy) > + visitDir(".", ".h", cTidy) > + visitDir(".", ".def", m2Tidy) > + visitDir(".", ".mod", m2Tidy) > + > + > +main() > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/boilerplate.py > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/boilerplate.py 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,548 @@ > +#!/usr/bin/env python3 > +# > +# boilerplate.py utility to rewrite the boilerplate with new dates. > +# > +# Copyright (C) 2018-2022 Free Software Foundation, Inc. > +# Contributed by Gaius Mulley . > +# > +# This file is part of GNU Modula-2. > +# > +# GNU Modula-2 is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3, or (at your option) > +# any later version. > +# > +# GNU Modula-2 is distributed in the hope that it will be useful, but > +# WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +# General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with GNU Modula-2; see the file COPYING3. If not see > +# . > +# > + > +import argparse > +import datetime > +import os > +import sys > + > + > +errorCount = 0 > +seenFiles = [] > +outputName = None > + > +ISO_COPYRIGHT = "Copyright ISO/IEC" > +COPYRIGHT = "Copyright (C)" > +GNU_PUBLIC_LICENSE = "GNU General Public License" > +GNU_LESSER_GENERAL = "GNU Lesser General" > +GCC_RUNTIME_LIB_EXC = "GCC Runtime Library Exception" > +VERSION_2_1 = "version 2.1" > +VERSION_2 = "version 2" > +VERSION_3 = "version 3" > +Licenses = {VERSION_2_1: "v2.1", VERSION_2: "v2", VERSION_3: "v3"} > +CONTRIBUTED_BY = "ontributed by" > + > + > +def printf(fmt, *args): > + # printf - keeps C programmers happy :-) > + print(str(fmt) % args, end=' ') > + > + > +def error(fmt, *args): > + # error - issue an error message. > + global errorCount > + > + print(str(fmt) % args, end=' ') > + errorCount += 1 > + > + > +def haltOnError(): > + if errorCount > 0: > + os.sys.exit(1) > + > + > +def basename(f): > + b = f.split("/") > + return b[-1] > + > + > +def analyseComment(text, f): > + # analyseComment determine the license from the top comment. > + start_date, end_date = None, None > + contribution, summary, lic = None, None, None > + if text.find(ISO_COPYRIGHT) > 0: > + lic = "BSISO" > + now = datetime.datetime.now() > + for d in range(1984, now.year+1): > + if text.find(str(d)) > 0: > + if start_date is None: > + start_date = str(d) > + end_date = str(d) > + return start_date, end_date, "", "", lic > + elif text.find(COPYRIGHT) > 0: > + if text.find(GNU_PUBLIC_LICENSE) > 0: > + lic = "GPL" > + elif text.find(GNU_LESSER_GENERAL) > 0: > + lic = "LGPL" > + for license in Licenses.keys(): > + if text.find(license) > 0: > + lic += Licenses[license] > + if text.find(GCC_RUNTIME_LIB_EXC) > 0: > + lic += "x" > + now = datetime.datetime.now() > + for d in range(1984, now.year+1): > + if text.find(str(d)) > 0: > + if start_date is None: > + start_date = str(d) > + end_date = str(d) > + if text.find(CONTRIBUTED_BY) > 0: > + i = text.find(CONTRIBUTED_BY) > + i += len(CONTRIBUTED_BY) > + j = text.index(". ", i) > + contribution = text[i:j] > + if text.find(basename(f)) > 0: > + i = text.find(basename(f)) > + j = text.find(". ", i) > + if j < 0: > + error('summary of the file does not finish with a "."') > + summary = text[i:] > + else: > + summary = text[i:j] > + return start_date, end_date, contribution, summary, lic > + > + > +def analyseHeaderWithoutTerminator(f, start): > + text = "" > + for count, l in enumerate(open(f).readlines()): > + parts = l.split(start) > + if len(parts) > 1: > + line = start.join(parts[1:]) > + line = line.strip() > + text += " " > + text += line > + elif (l.rstrip() != "") and (len(parts[0]) > 0): > + return analyseComment(text, f), count > + return [None, None, None, None, None], 0 > + > + > +def analyseHeaderWithTerminator(f, start, end): > + inComment = False > + text = "" > + for count, line in enumerate(open(f).readlines()): > + while line != "": > + line = line.strip() > + if inComment: > + text += " " > + pos = line.find(end) > + if pos >= 0: > + text += line[:pos] > + line = line[pos:] > + inComment = False > + else: > + text += line > + line = "" > + else: > + pos = line.find(start) > + if (pos >= 0) and (len(line) > len(start)): > + before = line[:pos].strip() > + if before != "": > + return analyseComment(text, f), count > + line = line[pos + len(start):] > + inComment = True > + elif (line != "") and (line == end): > + line = "" > + else: > + return analyseComment(text, f), count > + return [None, None, None, None, None], 0 > + > + > +def analyseHeader(f, start, end): > + # analyseHeader - > + if end is None: > + return analyseHeaderWithoutTerminator(f, start) > + else: > + return analyseHeaderWithTerminator(f, start, end) > + > + > +def addStop(sentence): > + # addStop - add a full stop to a sentance. > + if sentence is None: > + return None > + sentence = sentence.rstrip() > + if (len(sentence) > 0) and (sentence[-1] != "."): > + return sentence + "." > + return sentence > + > + > +GPLv3 = """ > +%s > + > +Copyright (C) %s Free Software Foundation, Inc. > +Contributed by %s > + > +This file is part of GNU Modula-2. > + > +GNU Modula-2 is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3, or (at your option) > +any later version. > + > +GNU Modula-2 is distributed in the hope that it will be useful, but > +WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with GNU Modula-2; see the file COPYING3. If not see > +. > +""" > + > +GPLv3x = """ > +%s > + > +Copyright (C) %s Free Software Foundation, Inc. > +Contributed by %s > + > +This file is part of GNU Modula-2. > + > +GNU Modula-2 is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3, or (at your option) > +any later version. > + > +GNU Modula-2 is distributed in the hope that it will be useful, but > +WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +General Public License for more details. > + > +Under Section 7 of GPL version 3, you are granted additional > +permissions described in the GCC Runtime Library Exception, version > +3.1, as published by the Free Software Foundation. > + > +You should have received a copy of the GNU General Public License and > +a copy of the GCC Runtime Library Exception along with this program; > +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > +. > +""" > + > +LGPLv3 = """ > +%s > + > +Copyright (C) %s Free Software Foundation, Inc. > +Contributed by %s > + > +This file is part of GNU Modula-2. > + > +GNU Modula-2 is free software: you can redistribute it and/or modify > +it under the terms of the GNU Lesser General Public License as > +published by the Free Software Foundation, either version 3 of the > +License, or (at your option) any later version. > + > +GNU Modula-2 is distributed in the hope that it will be useful, but > +WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +Lesser General Public License for more details. > + > +You should have received a copy of the GNU Lesser General Public License > +along with GNU Modula-2. If not, see . > +""" > + > +BSISO = """ > +Library module defined by the International Standard > + Information technology - programming languages > + BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language. > + > + Copyright ISO/IEC (International Organization for Standardization > + and International Electrotechnical Commission) %s. > + > + It may be freely copied for the purpose of implementation (see page > + 707 of the Information technology - Programming languages Part 1: > + Modula-2, Base Language. BS ISO/IEC 10514-1:1996). > +""" > + > +templates = {} > +templates["GPLv3"] = GPLv3 > +templates["GPLv3x"] = GPLv3x > +templates["LGPLv3"] = LGPLv3 > +templates["LGPLv2.1"] = LGPLv3 > +templates["BSISO"] = BSISO > + > + > +def writeTemplate(fo, magic, start, end, dates, contribution, summary, lic): > + if lic in templates: > + if lic == "BSISO": > + # non gpl but freely distributed for the implementation of a > + # compiler > + text = templates[lic] % (dates) > + text = text.rstrip() > + else: > + summary = summary.lstrip() > + contribution = contribution.lstrip() > + summary = addStop(summary) > + contribution = addStop(contribution) > + if magic is not None: > + fo.write(magic) > + fo.write("\n") > + text = templates[lic] % (summary, dates, contribution) > + text = text.rstrip() > + if end is None: > + text = text.split("\n") > + for line in text: > + fo.write(start) > + fo.write(" ") > + fo.write(line) > + fo.write("\n") > + else: > + text = text.lstrip() > + fo.write(start) > + fo.write(" ") > + fo.write(text) > + fo.write(" ") > + fo.write(end) > + fo.write("\n") > + # add a blank comment line for a script for eye candy. > + if start == "#" and end is None: > + fo.write(start) > + fo.write("\n") > + else: > + error("no template found for: %s\n", lic) > + os.sys.exit(1) > + return fo > + > + > +def writeBoilerPlate(fo, magic, start, end, > + start_date, end_date, contribution, summary, gpl): > + if start_date == end_date: > + dates = start_date > + else: > + dates = "%s-%s" % (start_date, end_date) > + return writeTemplate(fo, magic, start, end, > + dates, contribution, summary, gpl) > + > + > +def rewriteFile(f, magic, start, end, start_date, end_date, > + contribution, summary, gpl, lines): > + text = "".join(open(f).readlines()[lines:]) > + if outputName == "-": > + fo = sys.stdout > + else: > + fo = open(f, "w") > + fo = writeBoilerPlate(fo, magic, start, end, > + start_date, end_date, contribution, summary, gpl) > + fo.write(text) > + fo.flush() > + if outputName != "-": > + fo.close() > + > + > +def handleHeader(f, magic, start, end): > + # handleHeader keep reading lines of file, f, looking for start, end > + # sequences and comments inside. The comments are checked for: > + # date, contribution, summary > + global errorCount > + > + errorCount = 0 > + [start_date, end_date, > + contribution, summary, lic], lines = analyseHeader(f, start, end) > + if lic is None: > + error("%s:1:no GPL found at the top of the file\n", f) > + else: > + if args.verbose: > + printf("copyright: %s\n", lic) > + if (start_date is not None) and (end_date is not None): > + if start_date == end_date: > + printf("dates = %s\n", start_date) > + else: > + printf("dates = %s-%s\n", start_date, end_date) > + if summary is not None: > + printf("summary: %s\n", summary) > + if contribution is not None: > + printf("contribution: %s\n", contribution) > + if start_date is None: > + error("%s:1:no date found in the GPL at the top of the file\n", f) > + if args.contribution is None: > + if contribution == "": > + error("%s:1:no contribution found in the " + > + "GPL at the top of the file\n", f) > + else: > + contribution = args.contribution > + if summary is None: > + if args.summary == "": > + error("%s:1:no single line summary found in the " + > + "GPL at the top of the file\n", f) > + else: > + summary = args.summary > + if errorCount == 0: > + now = datetime.datetime.now() > + if args.no: > + print(f, "suppressing change as requested: %s-%s %s" > + % (start_date, end_date, lic)) > + else: > + if lic == "BSISO": > + # don't change the BS ISO license! > + pass > + elif args.extensions: > + lic = "GPLv3x" > + elif args.gpl3: > + lic = "GPLv3" > + rewriteFile(f, magic, start, end, start_date, > + str(now.year), contribution, summary, lic, lines) > + else: > + printf("too many errors, no modifications will occur\n") > + > + > +def bashTidy(f): > + # bashTidy tidy up dates using '#' comment > + handleHeader(f, "#!/bin/bash", "#", None) > + > + > +def pythonTidy(f): > + # pythonTidy tidy up dates using '#' comment > + handleHeader(f, "#!/usr/bin/env python3", '#', None) > + > + > +def bnfTidy(f): > + # bnfTidy tidy up dates using '--' comment > + handleHeader(f, None, '--', None) > + > + > +def cTidy(f): > + # cTidy tidy up dates using '/* */' comments > + handleHeader(f, None, '/*', '*/') > + > + > +def m2Tidy(f): > + # m2Tidy tidy up dates using '(* *)' comments > + handleHeader(f, None, '(*', '*)') > + > + > +def inTidy(f): > + # inTidy tidy up dates using '#' as a comment and check > + # the first line for magic number. > + first = open(f).readlines()[0] > + if (len(first) > 0) and (first[:2] == "#!"): > + # magic number found, use this > + handleHeader(f, first, "#", None) > + else: > + handleHeader(f, None, "#", None) > + > + > +def doVisit(args, dirname, names): > + # doVisit helper function to call func on every extension file. > + global outputName > + func, extension = args > + for f in names: > + if len(f) > len(extension) and f[-len(extension):] == extension: > + outputName = f > + func(os.path.join(dirname, f)) > + > + > +def visitDir(startDir, ext, func): > + # visitDir call func for each file in startDir which has ext. > + global outputName, seenFiles > + for dirName, subdirList, fileList in os.walk(startDir): > + for fname in fileList: > + if (len(fname) > len(ext)) and (fname[-len(ext):] == ext): > + fullpath = os.path.join(dirName, fname) > + outputName = fullpath > + if not (fullpath in seenFiles): > + seenFiles += [fullpath] > + func(fullpath) > + # Remove the first entry in the list of sub-directories > + # if there are any sub-directories present > + if len(subdirList) > 0: > + del subdirList[0] > + > + > +def findFiles(): > + # findFiles for each file extension call the appropriate tidy routine. > + visitDir(args.recursive, '.h.in', cTidy) > + visitDir(args.recursive, '.in', inTidy) > + visitDir(args.recursive, '.sh', inTidy) > + visitDir(args.recursive, '.py', pythonTidy) > + visitDir(args.recursive, '.c', cTidy) > + visitDir(args.recursive, '.h', cTidy) > + visitDir(args.recursive, '.cc', cTidy) > + visitDir(args.recursive, '.def', m2Tidy) > + visitDir(args.recursive, '.mod', m2Tidy) > + visitDir(args.recursive, '.bnf', bnfTidy) > + > + > +def handleArguments(): > + # handleArguments create and return the args object. > + parser = argparse.ArgumentParser() > + parser.add_argument("-c", "--contribution", > + help="set the contribution string " + > + "at the top of the file.", > + default="", action="store") > + parser.add_argument("-d", "--debug", help="turn on internal debugging.", > + default=False, action="store_true") > + parser.add_argument("-f", "--force", > + help="force a check to insist that the " + > + "contribution, summary and GPL exist.", > + default=False, action="store_true") > + parser.add_argument("-g", "--gplv3", help="change to GPLv3", > + default=False, action="store_true") > + parser.add_argument("-o", "--outputfile", help="set the output file", > + default="-", action="store") > + parser.add_argument("-r", "--recursive", > + help="recusively scan directory for known file " + > + "extensions (.def, .mod, .c, .h, .py, .in, .sh).", > + default=".", action="store") > + parser.add_argument("-s", "--summary", > + help="set the summary line for the file.", > + default=None, action="store") > + parser.add_argument("-u", "--update", help="update all dates.", > + default=False, action="store_true") > + parser.add_argument("-v", "--verbose", > + help="display copyright, " + > + "date and contribution messages", > + action="store_true") > + parser.add_argument("-x", "--extensions", > + help="change to GPLv3 with GCC runtime extensions.", > + default=False, action="store_true") > + parser.add_argument("-N", "--no", > + help="do not modify any file.", > + action="store_true") > + args = parser.parse_args() > + return args > + > + > +def hasExt(name, ext): > + # hasExt return True if, name, ends with, ext. > + if len(name) > len(ext): > + return name[-len(ext):] == ext > + return False > + > + > +def singleFile(name): > + # singleFile scan the single file for a GPL boilerplate which > + # has a GPL, contribution field and a summary heading. > + if hasExt(name, ".def") or hasExt(name, ".mod"): > + m2Tidy(name) > + elif hasExt(name, ".h") or hasExt(name, ".c") or hasExt(name, ".cc"): > + cTidy(name) > + elif hasExt(name, ".in"): > + inTidy(name) > + elif hasExt(name, ".sh"): > + inTidy(name) # uses magic number for actual sh/bash > + elif hasExt(name, ".py"): > + pythonTidy(name) > + > + > +def main(): > + # main - handleArguments and then find source files. > + global args, outputName > + args = handleArguments() > + outputName = args.outputfile > + if args.recursive: > + findFiles() > + elif args.inputfile is None: > + print("an input file must be specified on the command line") > + else: > + singleFile(args.inputfile) > + haltOnError() > + > + > +main() > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/buildpg > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/buildpg 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,289 @@ > +#!/bin/sh > + > +# Copyright (C) 2000-2022 Free Software Foundation, Inc. > +# This file is part of GNU Modula-2. > +# > +# GNU Modula-2 is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3, or (at your option) > +# any later version. > +# > +# GNU Modula-2 is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with GNU Modula-2; see the file COPYING. If not, write to the > +# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA > +# 02110-1301, USA. > +# > + > +# builds the pg.bnf from ppg.mod > +# usage buildpg ppg.mod destination [-e] > +# -e build without error recovery > +# > +PPGSRC=$1 > +PPGDST=$2 > + > +includeNonErrorChecking () { > + sed -e "1,/StartNonErrorChecking/d" < $PPGSRC |\ > + sed -e "1,/EndNonErrorChecking/!d" > +} > + > +includeErrorChecking () { > + sed -e "1,/StartErrorChecking/d" < $PPGSRC |\ > + sed -e "1,/EndErrorChecking/!d" > +} > + > + > +echo "% module" $PPGDST "begin" > +sed -e "1,/% declaration/!d" < $PPGSRC | sed -e "s/ppg/${PPGDST}/g" > + > +echo "% declaration" $PPGDST "begin" > + > +sed -e "1,/% declaration/d" < $PPGSRC | sed -e "1,/% rules/!d" | sed -e "s/ppg/${PPGDST}/g" > + > +if [ "$3" = "-e" ] ; then > + includeNonErrorChecking > + echo "% module" $PPGDST "end" > + sed -e "1,/% module pg end/d" < $PPGSRC | sed -e "s/ppg/${PPGDST}/g" > +else > + includeErrorChecking > + echo "% module" $PPGDST "end" > + sed -e "1,/% module pg end/d" < $PPGSRC | sed -e "s/ppg/${PPGDST}/g" |\ > + sed -e "s/WasNoError := Main() ;/Main({eoftok}) ;/" > +fi > + > +echo "% rules" > + > +cat << EOFEOF | sed -e "s/ppg/${PPGDST}/g" > +error 'WarnError' 'WarnString' > +tokenfunc 'GetCurrentTokenType()' > + > +token 'identifier' identtok -- internal token > +token 'literal' literaltok > +token '%' codetok > +token ':=' lbecomestok > +token '=:' rbecomestok > +token '|' bartok > +token '[' lsparatok > +token ']' rsparatok > +token '{' lcparatok -- left curly para > +token '}' rcparatok -- right curly para > +token '(' lparatok > +token ')' rparatok > +token "error" errortok > +token "tokenfunc" tfunctok > +token "symfunc" symfunctok > +token '"' dquotetok > +token "'" squotetok > +token "module" moduletok > +token "begin" begintok > +token "rules" rulestok > +token "end" endtok > +token '<' lesstok > +token '>' gretok > +token "token" tokentok > +token "special" specialtok > +token "first" firsttok > +token "follow" followtok > +token "BNF" BNFtok > +token "FNB" FNBtok > +token "declaration" declarationtok > +token "epsilon" epsilontok > +token '' eoftok -- internal token > + > +special Ident first { < identtok > } follow { } > +special Modula2Code first { } follow { '%' } > +special StartModName first { < identtok > } follow { } > +special EndModName first { < identtok > } follow { } > +special DoDeclaration first { < identtok > } follow { } > +special CollectLiteral first { < literaltok > } follow { } > +special CollectTok first { < identtok > } follow { } > +special DefineToken first { < identtok > } follow { } > + > +BNF > + > +Rules := "%" "rules" { Defs } ExtBNF =: > + > +Special := Ident > + % VAR p: ProductionDesc ; % > + % p := NewProduction() ; > + p^.statement := NewStatement() ; > + p^.statement^.followinfo^.calcfollow := TRUE ; > + p^.statement^.followinfo^.epsilon := false ; > + p^.statement^.followinfo^.reachend := false ; > + p^.statement^.ident := CurrentIdent ; > + p^.statement^.expr := NIL ; > + p^.firstsolved := TRUE ; > + p^.followinfo^.calcfollow := TRUE ; > + p^.followinfo^.epsilon := false ; > + p^.followinfo^.reachend := false % > + First Follow [ "epsilon" % p^.statement^.followinfo^.epsilon := true ; (* these are not used - but they are displayed when debugging *) > + p^.statement^.followinfo^.reachend := true ; > + p^.followinfo^.epsilon := true ; > + p^.followinfo^.reachend := true > + % ] > + [ Literal % p^.description := LastLiteral % ] > + =: > + > +Factor := "%" Modula2Code "%" | > + Ident % WITH CurrentFactor^ DO > + type := id ; > + ident := CurrentIdent > + END ; % | > + Literal % WITH CurrentFactor^ DO > + type := lit ; > + string := LastLiteral ; > + IF GetSymKey(Aliases, LastLiteral)=NulName > + THEN > + WarnError1('no token defined for literal %s', LastLiteral) > + END > + END ; % | > + "{" % WITH CurrentFactor^ DO > + type := mult ; > + expr := NewExpression() ; > + CurrentExpression := expr ; > + END ; % > + Expression "}" | > + "[" % WITH CurrentFactor^ DO > + type := opt ; > + expr := NewExpression() ; > + CurrentExpression := expr ; > + END ; % > + Expression "]" | > + "(" % WITH CurrentFactor^ DO > + type := sub ; > + expr := NewExpression() ; > + CurrentExpression := expr ; > + END ; % > + Expression ")" =: > + > +Statement := % VAR i: IdentDesc ; % > + Ident > + % VAR p: ProductionDesc ; % > + % p := FindDefinition(CurrentIdent^.name) ; > + IF p=NIL > + THEN > + p := NewProduction() > + ELSE > + IF NOT ((p^.statement=NIL) OR (p^.statement^.expr=NIL)) > + THEN > + WarnError1('already declared rule %s', CurrentIdent^.name) > + END > + END ; > + i := CurrentIdent ; % > + ":=" > + % VAR e: ExpressionDesc ; % > + % e := NewExpression() ; > + CurrentExpression := e ; % > + % VAR s: StatementDesc ; % > + % s := NewStatement() ; > + WITH s^ DO > + ident := i ; > + expr := e > + END ; % > + Expression > + % p^.statement := s ; % > + "=:" =: > + > +Defs := "special" Special | "token" Token | "error" ErrorProcedures | > + "tokenfunc" TokenProcedure | "symfunc" SymProcedure =: > +ExtBNF := "BNF" { Production } "FNB" =: > +Main := Header Decls Footer Rules =: > +Header := "%" "module" StartModName =: > +Decls := "%" "declaration" DoDeclaration =: > +Footer := "%" "module" EndModName =: > + > +First := "first" "{" { LitOrTokenOrIdent > + % WITH CurrentSetDesc^ DO > + next := TailProduction^.first ; > + END ; > + TailProduction^.first := CurrentSetDesc > + % > + } "}" =: > +Follow := "follow" "{" { LitOrTokenOrIdent > + % WITH CurrentSetDesc^ DO > + next := TailProduction^.followinfo^.follow ; > + END ; > + TailProduction^.followinfo^.follow := CurrentSetDesc > + % > + } "}" =: > +LitOrTokenOrIdent := Literal % CurrentSetDesc := NewSetDesc() ; > + WITH CurrentSetDesc^ DO > + type := litel ; > + string := LastLiteral ; > + END ; > + % | > + '<' CollectTok '>' | > + Ident % CurrentSetDesc := NewSetDesc() ; > + WITH CurrentSetDesc^ DO > + type := idel ; > + ident := CurrentIdent ; > + END ; > + % =: > + > +Literal := '"' CollectLiteral '"' | > + "'" CollectLiteral "'" =: > + > +CollectTok := % CurrentSetDesc := NewSetDesc() ; > + WITH CurrentSetDesc^ DO > + type := tokel ; > + string := GetCurrentToken() ; > + END ; > + IF NOT ContainsSymKey(Values, GetCurrentToken()) > + THEN > + AddEntry(Values, GetCurrentToken(), LargestValue) ; > + AddEntry(ReverseValues, Name(LargestValue), GetCurrentToken()) ; > + AddEntry(Aliases, GetCurrentToken(), GetCurrentToken()) ; > + AddEntry(ReverseAliases, GetCurrentToken(), GetCurrentToken()) ; > + INC(LargestValue) > + END ; > + AdvanceToken() ; % =: > + > +CollectLiteral := % LastLiteral := GetCurrentToken() ; > + AdvanceToken ; % =: > + > +DefineToken := % AddEntry(Aliases, LastLiteral, GetCurrentToken()) ; > + AddEntry(ReverseAliases, GetCurrentToken(), LastLiteral) ; > + AddEntry(Values, GetCurrentToken(), LargestValue) ; > + AddEntry(ReverseValues, Name(LargestValue), GetCurrentToken()) ; > + INC(LargestValue) ; > + AdvanceToken ; % =: > + > +Token := Literal DefineToken =: > + > +ErrorProcedures := Literal % ErrorProcArray := LastLiteral % > + Literal % ErrorProcString := LastLiteral % =: > +TokenProcedure := Literal % TokenTypeProc := LastLiteral % =: > +SymProcedure := Literal % SymIsProc := LastLiteral % =: > + > +Production := Statement =: > +Expression := % VAR t1, t2: TermDesc ; > + e : ExpressionDesc ; % > + % e := CurrentExpression ; > + t1 := NewTerm() ; > + CurrentTerm := t1 ; % > + Term % e^.term := t1 ; % > + { "|" % t2 := NewTerm() ; > + CurrentTerm := t2 % > + Term % t1^.next := t2 ; > + t1 := t2 % } =: > + > +Term := % VAR t1: TermDesc ; f1, f2: FactorDesc ; % > + % CurrentFactor := NewFactor() ; > + f1 := CurrentFactor ; > + t1 := CurrentTerm ; % > + Factor % t1^.factor := f1 ; > + f2 := NewFactor() ; > + CurrentFactor := f2 % > + { Factor % f1^.next := f2 ; > + f1 := f2 ; > + f2 := NewFactor() ; > + CurrentFactor := f2 ; % } > + =: > + > +FNB > + > +EOFEOF > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/calcpath > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/calcpath 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,51 @@ > +#!/bin/sh > + > +# calcpath return a path which is $1/$2/$3 when $2 is relative and $2/$3 if absolute. > + > +# Copyright (C) 2021-2022 Free Software Foundation, Inc. > +# Contributed by Gaius Mulley . > +# > +# This file is part of GNU Modula-2. > +# > +# GNU Modula-2 is free software; you can redistribute it and/or modify it under > +# the terms of the GNU General Public License as published by the Free > +# Software Foundation; either version 3, or (at your option) any later > +# version. > +# > +# GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY > +# WARRANTY; without even the implied warranty of MERCHANTABILITY or > +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +# for more details. > +# > +# You should have received a copy of the GNU General Public License along > +# with gm2; see the file COPYING. If not, write to the Free Software > +# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) > + > + > +Usage () { > + echo "Usage: calcpath pathcomponent1 pathcomponent2 subdir" > + echo -n " if pathcomponent1 is relative then pathcomponent1/pathcomponet2/subdir is" > + echo " returned" > + echo " otherwise pathcomponet2/subdir is returned" > + echo " the path is checked for legality in subdir." > +} > + > + > +if [ $# -eq 3 ]; then > + if [ "$(echo $2 | cut -b 1)" = "." ] ; then > + # relative path > + the_path=$1/$2/$3 > + else > + the_path=$2/$3 > + fi > + cd $3 > + if realpath ${the_path} > /dev/null ; then > + echo ${the_path} > + else > + echo "calcpath: error ${the_path} is not a valid path in subdirectory $3" 1>&2 > + exit 1 > + fi > +else > + Usage > + exit 1 > +fi > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/makeSystem > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/makeSystem 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,108 @@ > +#!/bin/sh > + > +# makeSystem creates a target SYSTEM.def using the appropriate dialect template. > + > +# Copyright (C) 2008-2022 Free Software Foundation, Inc. > +# Contributed by Gaius Mulley . > +# > +# This file is part of GNU Modula-2. > +# > +# GNU Modula-2 is free software; you can redistribute it and/or modify it under > +# the terms of the GNU General Public License as published by the Free > +# Software Foundation; either version 3, or (at your option) any later > +# version. > +# > +# GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY > +# WARRANTY; without even the implied warranty of MERCHANTABILITY or > +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +# for more details. > +# > +# You should have received a copy of the GNU General Public License along > +# with gm2; see the file COPYING. If not, write to the Free Software > +# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) > + > + > +Usage () { > + echo "Usage: makesystem dialectflag SYSTEM.def SYSTEM.mod librarypath compiler" > +} > + > +if [ $# -lt 6 ] ; then > + Usage > + exit 1 > +fi > + > +DIALECT=$1 > +SYSTEMDEF=$2 > +SYSTEMMOD=$3 > +LIBRARY=$4 > +COMPILER=$5 > +OUTPUTFILE=$6 > + > +if [ "$COMPILER" = "" ] ; then > + echo "parameter 5 of makeSystem is incorrect, GM2_FOR_TARGET was unset" > + exit 1 > +fi > + > +if [ "$DIALECT" != "-fiso" -a "$DIALECT" != "-fpim" ] ; then > + Usage > + echo "dialect must be -fiso or -fpim" > + exit 1 > +fi > + > +displayExportedTypes () { > + n=1 > + c=0 > + for i in ${types} ; do > + if [ $n -eq 1 ] ; then > + n=0 > + echo -n " " >> ${OUTPUTFILE} > + fi > + echo -n "$i, " >> ${OUTPUTFILE} > + if [ $c -eq 4 ] ; then > + echo " " >> ${OUTPUTFILE} > + n=1 > + c=0 > + fi > + c=`expr $c + 1` > + done > + echo " " >> ${OUTPUTFILE} > +} > + > +displayBuiltinTypes () { > + for i in ${types} ; do > + echo " $i ; " >> ${OUTPUTFILE} > + done > +} > + > +displayStart () { > + sed -e "1,/@SYSTEM_DATATYPES@/!d" < ${SYSTEMDEF} | \ > + sed -e "/@SYSTEM_DATATYPES@/d" >> ${OUTPUTFILE} > +} > + > +displayMiddle () { > + sed -e "1,/@SYSTEM_DATATYPES@/d" < ${SYSTEMDEF} | \ > + sed -e "1,/@SYSTEM_TYPES@/!d" | \ > + sed -e "/@SYSTEM_TYPES@/d" >> ${OUTPUTFILE} > +} > + > +displayEnd () { > + sed -e "1,/@SYSTEM_TYPES@/d" < ${SYSTEMDEF} >> ${OUTPUTFILE} > +} > + > +MINIMAL="-fno-scaffold-main -fno-scaffold-dynamic -fno-scaffold-static -fno-m2-plugin" > + > +rm -f ${OUTPUTFILE} > +if ${COMPILER} ${DIALECT} ${LIBRARY} ${MINIMAL} \ > + -c -fdump-system-exports ${SYSTEMMOD} -o /dev/null 2>&1 > /dev/null ; then > + types=`${COMPILER} ${DIALECT} ${LIBRARY} ${MINIMAL} -fno-m2-plugin -c -fdump-system-exports ${SYSTEMMOD} -o /dev/null | cut -f5 -d' '` > + touch ${OUTPUTFILE} > + displayStart > + displayExportedTypes > + displayMiddle > + displayBuiltinTypes > + displayEnd > +else > + ${COMPILER} ${DIALECT} ${LIBRARY} ${MINIMAL} \ > + -c -fdump-system-exports ${SYSTEMMOD} -o /dev/null > + exit $? > +fi > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/README > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/README 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,3 @@ > +This directory contains miscellaneous scripts and programs (mklink.c) > +to allow for bootstrap linking and creating library documentation from > +sources. > \ No newline at end of file > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/def2doc.py > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/def2doc.py 2022-11-05 17:33:53.685584357 +0000 > @@ -0,0 +1,419 @@ > +#!/usr/bin/env python3 > + > +# def2doc.py creates texi library documentation for all exported procedures. > +# Contributed by Gaius Mulley . > + > +# Copyright (C) 2000-2022 Free Software Foundation, Inc. > +# This file is part of GNU Modula-2. > +# > +# GNU Modula-2 is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3, or (at your option) > +# any later version. > +# > +# GNU Modula-2 is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with GNU Modula-2; see the file COPYING. If not, write to the > +# Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA > +# 02110-1301, USA. > +# > + > +import argparse > +import os > +import sys > + > +BaseLibs = ["gm2-libs", "Base libraries", "Basic M2F compatible libraries"] > + > +PIMLogDesc = "PIM and Logitech 3.0 compatible libraries" > +PIMLog = ["gm2-libs-pim", "PIM and Logitech 3.0 Compatible", PIMLogDesc] > +PIMCorDesc = "PIM compatible process support" > +PIMCor = ["gm2-libs-coroutines", "PIM coroutine support", PIMCorDesc] > +ISOLibs = ["gm2-libs-iso", "M2 ISO Libraries", "ISO defined libraries"] > + > +libraryClassifications = [BaseLibs, PIMLog, PIMCor, ISOLibs] > + > + > +def initState(): > + global inVar, inType, inConst > + inVar, inType, inConst = False, False, False > + > + > +def emitNode(name, nxt, previous, up): > + if args.texinfo: > + output.write("@node " + name + ", " + nxt + ", ") > + output.write(previous + ", " + up + "\n") > + elif args.sphinx: > + output.write("@c @node " + name + ", " + nxt + ", ") > + output.write(previous + ", " + up + "\n") > + > + > +def emitSection(name): > + if args.texinfo: > + output.write("@section " + name + "\n") > + elif args.sphinx: > + output.write(name + "\n") > + output.write("=" * len(name) + "\n") > + > + > +def emitSubSection(name): > + if args.texinfo: > + output.write("@subsection " + name + "\n") > + elif args.sphinx: > + output.write(name + "\n") > + output.write("-" * len(name) + "\n") > + > + > +def displayLibraryClass(): > + # displayLibraryClass displays a node for a library directory and invokes > + # a routine to summarize each module. > + global args > + previous = "" > + nxt = libraryClassifications[1][1] > + i = 0 > + lib = libraryClassifications[i] > + while True: > + emitNode(lib[1], nxt, previous, args.up) > + emitSection(lib[1]) > + output.write("\n") > + displayModules(lib[1], lib[0], args.builddir, args.sourcedir) > + output.write("\n") > + output.write("@c " + "-" * 60 + "\n") > + previous = lib[1] > + i += 1 > + if i == len(libraryClassifications): > + break > + lib = libraryClassifications[i] > + if i+1 == len(libraryClassifications): > + nxt = "" > + else: > + nxt = libraryClassifications[i+1][1] > + > + > +def displayMenu(): > + # displayMenu displays the top level menu for library documentation. > + output.write("@menu\n") > + for lib in libraryClassifications: > + output.write("* " + lib[1] + "::" + lib[2] + "\n") > + output.write("@end menu\n") > + output.write("\n") > + output.write("@c " + "=" * 60 + "\n") > + output.write("\n") > + > + > +def removeInitialComments(file, line): > + # removeInitialComments removes any (* *) at the top > + # of the definition module. > + while (str.find(line, "*)") == -1): > + line = file.readline() > + > + > +def removeableField(line): > + # removeableField - returns True if a comment field should be removed > + # from the definition module. > + field_list = ["Author", "Last edit", "LastEdit", "Last update", > + "Date", "Title", "Revision"] > + for field in field_list: > + if (str.find(line, field) != -1) and (str.find(line, ":") != -1): > + return True > + ignore_list = ["System", "SYSTEM"] > + for ignore_field in ignore_list: > + if str.find(line, ignore_field) != -1: > + if str.find(line, ":") != -1: > + if str.find(line, "Description:") == -1: > + return True > + return False > + > + > +def removeFields(file, line): > + # removeFields removes Author/Date/Last edit/SYSTEM/Revision > + # fields from a comment within the start of a definition module. > + while (str.find(line, "*)") == -1): > + if not removeableField(line): > + output.write(str.replace(str.replace(str.rstrip(line), > + "{", "@{"), "}", "@}") + "\n") > + line = file.readline() > + output.write(str.rstrip(line) + "\n") > + > + > +def checkIndex(line): > + # checkIndex - create an index entry for a PROCEDURE, TYPE, CONST or VAR. > + global inVar, inType, inConst > + > + words = str.split(line) > + procedure = "" > + if (len(words) > 1) and (words[0] == "PROCEDURE"): > + inConst = False > + inType = False > + inVar = False > + if (words[1] == "__BUILTIN__") and (len(words) > 2): > + procedure = words[2] > + else: > + procedure = words[1] > + if (len(line) > 1) and (line[0:2] == "(*"): > + inConst = False > + inType = False > + inVar = False > + elif line == "VAR": > + inConst = False > + inVar = True > + inType = False > + return > + elif line == "TYPE": > + inConst = False > + inType = True > + inVar = False > + return > + elif line == "CONST": > + inConst = True > + inType = False > + inVar = False > + if inVar: > + words = str.split(line, ",") > + for word in words: > + word = str.lstrip(word) > + if word != "": > + if str.find(word, ":") == -1: > + output.write("@findex " + word + " (var)\n") > + elif len(word) > 0: > + var = str.split(word, ":") > + if len(var) > 0: > + output.write("@findex " + var[0] + " (var)\n") > + > + if inType: > + words = str.lstrip(line) > + if str.find(words, "=") != -1: > + word = str.split(words, "=") > + if (len(word[0]) > 0) and (word[0][0] != "_"): > + output.write("@findex " + str.rstrip(word[0]) + " (type)\n") > + else: > + word = str.split(words) > + if (len(word) > 1) and (word[1] == ";"): > + # hidden type > + if (len(word[0]) > 0) and (word[0][0] != "_"): > + output.write("@findex " + str.rstrip(word[0])) > + output.write(" (type)\n") > + if inConst: > + words = str.split(line, ";") > + for word in words: > + word = str.lstrip(word) > + if word != "": > + if str.find(word, "=") != -1: > + var = str.split(word, "=") > + if len(var) > 0: > + output.write("@findex " + var[0] + " (const)\n") > + if procedure != "": > + name = str.split(procedure, "(") > + if name[0] != "": > + proc = name[0] > + if proc[-1] == ";": > + proc = proc[:-1] > + if proc != "": > + output.write("@findex " + proc + "\n") > + > + > +def parseDefinition(dir, source, build, file, needPage): > + # parseDefinition reads a definition module and creates > + # indices for procedures, constants, variables and types. > + output.write("\n") > + with open(findFile(dir, build, source, file), "r") as f: > + initState() > + line = f.readline() > + while (str.find(line, "(*") != -1): > + removeInitialComments(f, line) > + line = f.readline() > + while (str.find(line, "DEFINITION") == -1): > + line = f.readline() > + output.write("@example\n") > + output.write(str.rstrip(line) + "\n") > + line = f.readline() > + if len(str.rstrip(line)) == 0: > + output.write("\n") > + line = f.readline() > + if (str.find(line, "(*") != -1): > + removeFields(f, line) > + else: > + output.write(str.rstrip(line) + "\n") > + else: > + output.write(str.rstrip(line) + "\n") > + line = f.readline() > + while line: > + line = str.rstrip(line) > + checkIndex(line) > + output.write(str.replace(str.replace(line, "{", "@{"), "}", "@}")) > + output.write("\n") > + line = f.readline() > + output.write("@end example\n") > + if needPage: > + output.write("@page\n") > + > + > +def parseModules(up, dir, build, source, listOfModules): > + previous = "" > + i = 0 > + if len(listOfModules) > 1: > + nxt = dir + "/" + listOfModules[1][:-4] > + else: > + nxt = "" > + while i < len(listOfModules): > + emitNode(dir + "/" + listOfModules[i][:-4], nxt, previous, up) > + emitSubSection(dir + "/" + listOfModules[i][:-4]) > + parseDefinition(dir, source, build, listOfModules[i], True) > + output.write("\n") > + previous = dir + "/" + listOfModules[i][:-4] > + i = i + 1 > + if i+1 < len(listOfModules): > + nxt = dir + "/" + listOfModules[i+1][:-4] > + else: > + nxt = "" > + > + > +def doCat(name): > + # doCat displays the contents of file, name, to stdout > + with open(name, "r") as file: > + line = file.readline() > + while line: > + output.write(str.rstrip(line) + "\n") > + line = file.readline() > + > + > +def moduleMenu(dir, build, source): > + # moduleMenu generates a simple menu for all definition modules > + # in dir > + output.write("@menu\n") > + listOfFiles = [] > + if os.path.exists(os.path.join(source, dir)): > + listOfFiles += os.listdir(os.path.join(source, dir)) > + if os.path.exists(os.path.join(source, dir)): > + listOfFiles += os.listdir(os.path.join(build, dir)) > + listOfFiles = list(dict.fromkeys(listOfFiles).keys()) > + listOfFiles.sort() > + for file in listOfFiles: > + if foundFile(dir, build, source, file): > + if (len(file) > 4) and (file[-4:] == ".def"): > + output.write("* " + dir + "/" + file[:-4] + "::" + file + "\n") > + output.write("@end menu\n") > + output.write("\n") > + > + > +def checkDirectory(dir, build, source): > + # checkDirectory - returns True if dir exists in either build or source. > + if os.path.isdir(build) and os.path.exists(os.path.join(build, dir)): > + return True > + elif os.path.isdir(source) and os.path.exists(os.path.join(source, dir)): > + return True > + else: > + return False > + > + > +def foundFile(dir, build, source, file): > + # foundFile return True if file is found in build/dir/file or > + # source/dir/file. > + name = os.path.join(os.path.join(build, dir), file) > + if os.path.exists(name): > + return True > + name = os.path.join(os.path.join(source, dir), file) > + if os.path.exists(name): > + return True > + return False > + > + > +def findFile(dir, build, source, file): > + # findFile return the path to file searching in build/dir/file > + # first then source/dir/file. > + name1 = os.path.join(os.path.join(build, dir), file) > + if os.path.exists(name1): > + return name1 > + name2 = os.path.join(os.path.join(source, dir), file) > + if os.path.exists(name2): > + return name2 > + sys.stderr.write("file cannot be found in either " + name1) > + sys.stderr.write(" or " + name2 + "\n") > + os.sys.exit(1) > + > + > +def displayModules(up, dir, build, source): > + # displayModules walks though the files in dir and parses > + # definition modules and includes README.texi > + if checkDirectory(dir, build, source): > + if foundFile(dir, build, source, "README.texi"): > + doCat(findFile(dir, build, source, "README.texi")) > + moduleMenu(dir, build, source) > + listOfFiles = [] > + if os.path.exists(os.path.join(source, dir)): > + listOfFiles += os.listdir(os.path.join(source, dir)) > + if os.path.exists(os.path.join(source, dir)): > + listOfFiles += os.listdir(os.path.join(build, dir)) > + listOfFiles = list(dict.fromkeys(listOfFiles).keys()) > + listOfFiles.sort() > + listOfModules = [] > + for file in listOfFiles: > + if foundFile(dir, build, source, file): > + if (len(file) > 4) and (file[-4:] == ".def"): > + listOfModules += [file] > + listOfModules.sort() > + parseModules(up, dir, build, source, listOfModules) > + else: > + line = "directory " + dir + " not found in either " > + line += build + " or " + source > + sys.stderr.write(line + "\n") > + > + > +def displayCopyright(): > + output.write("@c Copyright (C) 2000-2022 Free Software Foundation, Inc.\n") > + output.write("@c This file is part of GNU Modula-2.\n") > + output.write(""" > +@c Permission is granted to copy, distribute and/or modify this document > +@c under the terms of the GNU Free Documentation License, Version 1.2 or > +@c any later version published by the Free Software Foundation. > +""") > + > + > +def collectArgs(): > + parser = argparse.ArgumentParser() > + parser.add_argument("-v", "--verbose", help="generate progress messages", > + action="store_true") > + parser.add_argument("-b", "--builddir", help="set the build directory", > + default=".", action="store") > + parser.add_argument("-f", "--inputfile", help="set the input file", > + default=None, action="store") > + parser.add_argument("-o", "--outputfile", help="set the output file", > + default=None, action="store") > + parser.add_argument("-s", "--sourcedir", help="set the source directory", > + default=".", action="store") > + parser.add_argument("-t", "--texinfo", > + help="generate texinfo documentation", > + default=False, action="store_true") > + parser.add_argument("-u", "--up", help="set the up node", > + default="", action="store") > + parser.add_argument("-x", "--sphinx", help="generate sphinx documentation", > + default=False, action="store_true") > + args = parser.parse_args() > + return args > + > + > +def handleFile(): > + if args.inputfile is None: > + displayCopyright() > + displayMenu() > + displayLibraryClass() > + else: > + parseDefinition(".", args.sourcedir, args.builddir, > + args.inputfile, False) > + > + > +def main(): > + global args, output > + args = collectArgs() > + if args.outputfile is None: > + output = sys.stdout > + handleFile() > + else: > + with open(args.outputfile, "w") as output: > + handleFile() > + > + > +main() > diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/tools-src/mklink.c > --- /dev/null 2022-08-24 16:22:16.888000070 +0100 > +++ gcc-git-devel-modula2/gcc/m2/tools-src/mklink.c 2022-11-07 13:01:28.329424600 +0000 > @@ -0,0 +1,807 @@ > +/* mklink.c creates startup code and the link command line. > + > +Copyright (C) 2000-2022 Free Software Foundation, Inc. > +Contributed by Gaius Mulley . > + > +This file is part of GNU Modula-2. > + > +GNU Modula-2 is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3, or (at your option) > +any later version. > + > +GNU Modula-2 is distributed in the hope that it will be useful, but > +WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with GNU Modula-2; see the file COPYING3. If not see > +. */ > + > + > +#include "config.h" > +#include "system.h" > + > +#define MAX_FILE_NAME 8192 > +#define MAXSTACK 4096 > +#define STDIN 0 > +#define STDOUT 1 > +#define ENDOFILE ((char)-1) > +#define ERROR(X) \ > + (fprintf (stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) \ > + && (fflush (stderr))) > +#define DEBUG(X) \ > + ((Debug) && (fprintf (stderr, "%s\n", X) && (fflush (stderr)))) > + > +#if !defined(TRUE) > +#define TRUE (1 == 1) > +#endif > + > +#if !defined(FALSE) > +#define FALSE (1 == 0) > +#endif > + > +typedef struct functlist > +{ > + char *functname; > + struct functlist *next; > +} functList; > + > +/* Prototypes. */ > + > +static void ParseFileLinkCommand (void); > +static void ParseFileStartup (void); > +static void ParseFile (char *Name); > +static void ParseComments (void); > +static void CopyUntilEof (void); > +static void CopyUntilEol (void); > +static int IsSym (char *s); > +static int SymIs (char *s); > +static int FindString (char *String); > +static void GetNL (void); > +static char GetChar (void); > +static void ResetBuffer (void); > +static int GetSingleChar (char *ch); > +static int InRange (int Element, unsigned int Min, unsigned int Max); > +static char PutChar (char ch); > +static int IsSpace (char ch); > +static void SkipSpaces (void); > +static void SkipText (void); > +static void SilentSkipSpaces (void); > +static void SilentSkipText (void); > +static void PushBack (char *s); > +static int IsDigit (char ch); > +static void GetName (char *Name); > +static void OpenOutputFile (void); > +static void CloseFile (void); > +static void FindSource (char *Name); > +static void CopyUntilEolInto (char *Buffer); > +static void FindObject (char *Name); > +static int IsExists (char *Name); > + > +/* Global variables. */ > + > +static char *NameOfFile = NULL; > +static const char *NameOfMain = "main"; > +static int StackPtr = 0; > +static char Stack[MAXSTACK]; > +static int CurrentFile = STDIN; > +static int OutputFile; > +static int LinkCommandLine = FALSE; > +static int ProfilePCommand = FALSE; > +static int ProfilePGCommand = FALSE; > +static int ExitNeeded = TRUE; > +static char *libraries = NULL; > +static char *args = NULL; > +static functList *head = NULL; > +static functList *tail = NULL; > +static int langC = FALSE; /* FALSE = C++, TRUE = C. */ > + > +/* addLibrary - adds libname to the list of libraries to be linked. */ > + > +static void > +addLibrary (char *libname) > +{ > + if (libraries == NULL) > + libraries = strdup (libname); > + else > + { > + char *old = libraries; > + char *newlib > + = (char *)malloc (strlen (libname) + strlen (libraries) + 1 + 1); > + strcpy (newlib, libraries); > + strcat (newlib, " "); > + strcat (newlib, libname); > + libraries = newlib; > + free (old); > + } > +} > + > +/* addGccArg - adds arg to the list of gcc arguments. */ > + > +static void > +addGccArg (char *arg) > +{ > + if (args == NULL) > + args = strdup (arg); > + else > + { > + char *old = args; > + char *newarg = (char *)malloc (strlen (old) + strlen (arg) + 1 + 1); > + strcpy (newarg, old); > + strcat (newarg, " "); > + strcat (newarg, arg); > + args = newarg; > + free (old); > + } > +} > + > +int > +main (int argc, char *argv[]) > +{ > + int i; > + > + if (argc >= 3) > + { > + if (strcmp (argv[1], "-l") == 0) > + LinkCommandLine = TRUE; > + else if (strcmp (argv[1], "-s") == 0) > + LinkCommandLine = FALSE; > + else > + { > + fprintf (stderr, "Usage: mklink (-l|-s) [--langc|--langc++] [--pg|-p] " > + "[--lib library] [--main name] [--exit] --name " > + "filename \n"); > + fprintf (stderr, " must supply -l or -s option\n"); > + exit (1); > + } > + ProfilePCommand = FALSE; > + ProfilePGCommand = FALSE; > + i = 2; > + while (i < argc - 1) > + { > + if (strcmp (argv[i], "--langc++") == 0) > + langC = FALSE; > + else if (strcmp (argv[i], "--langc") == 0) > + langC = TRUE; > + else if (strncmp (argv[i], "-f", 2) == 0) > + addGccArg (argv[i]); > + else if (strcmp (argv[i], "--pg") == 0) > + ProfilePGCommand = TRUE; > + else if (strcmp (argv[i], "-p") == 0) > + ProfilePCommand = TRUE; > + else if (strcmp (argv[i], "--exit") == 0) > + ExitNeeded = FALSE; > + else if (strcmp (argv[i], "--lib") == 0) > + { > + i++; > + addLibrary (argv[i]); > + } > + else if (strcmp (argv[i], "--main") == 0) > + { > + i++; > + NameOfMain = argv[i]; > + } > + else if (strcmp (argv[i], "--name") == 0) > + { > + i++; > + NameOfFile = argv[i]; > + } > + i++; > + } > + ParseFile (argv[i]); > + } > + else > + { > + fprintf (stderr, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib " > + "library] [--main name] [--exit] --name filename " > + "\n"); > + exit (1); > + } > + if (NameOfFile == NULL) > + { > + fprintf (stderr, "mklink must have a --name argument\n"); > + fprintf (stderr, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib " > + "library] [--main name] [--exit] --name filename " > + "\n"); > + exit (1); > + } > + exit (0); > +} > + > +/* ParseFile - parses the input file and generates the output file. */ > + > +static void > +ParseFile (char *Name) > +{ > + FindSource (Name); > + OpenOutputFile (); > + if (LinkCommandLine) > + ParseFileLinkCommand (); > + else > + ParseFileStartup (); > + CloseFile (); > +} > + > +/* ParseFileLinkCommand - generates the link command. */ > + > +static void > +ParseFileLinkCommand (void) > +{ > + char name[MAX_FILE_NAME]; > + char *s = NULL; > + char *l = NULL; > + char *c = NULL; > + > + s = getenv ("CC"); > + if (s == NULL) > + { > + if (langC) > + printf ("gcc -g "); > + else > + printf ("g++ -g "); > + } > + else > + printf ("%s -g ", s); > + > + if (args != NULL) > + printf ("%s ", args); > + > + l = getenv ("LDFLAGS"); > + if (l != NULL) > + printf ("%s ", l); > + > + c = getenv ("CFLAGS"); > + if (c != NULL) > + printf ("%s ", c); > + > + if (ProfilePGCommand) > + printf (" -pg"); > + else if (ProfilePCommand) > + printf (" -p"); > + > + while (PutChar (GetChar ()) != (char)EOF) > + { > + CopyUntilEolInto (name); > + if ((strlen (name) > 0) && (name[0] != '#')) > + FindObject (name); > + } > + printf (" %s\n", libraries); > +} > + > +/* FindObject - searches the M2PATH variable to find the object file. > + If it finds the object file it prints it to stdout otherwise it > + writes an error on stderr. */ > + > +static void > +FindObject (char *Name) > +{ > + char m2search[4096]; > + char m2path[4096]; > + char name[4096]; > + char exist[4096]; > + int s, p; > + > + if (getenv ("M2PATH") == NULL) > + strcpy (m2path, "."); > + else > + strcpy (m2path, getenv ("M2PATH")); > + > + snprintf (name, sizeof (name), "%s.o", Name); > + p = 0; > + while (m2path[p] != (char)0) > + { > + s = 0; > + while ((m2path[p] != (char)0) && (m2path[p] != ' ')) > + { > + m2search[s] = m2path[p]; > + s++; > + p++; > + } > + if (m2path[p] == ' ') > + p++; > + m2search[s] = (char)0; > + snprintf (exist, sizeof (exist), "%s/%s", m2search, name); > + if (IsExists (exist)) > + { > + printf (" %s", exist); > + return; > + } > + } > + fprintf (stderr, "cannot find %s\n", name); > +} > + > +/* IsExists - returns true if a file, Name, exists. It returns false > + otherwise. */ > + > +static int > +IsExists (char *Name) > +{ > + struct stat buf; > + > + return (stat (Name, &buf) == 0); > +} > + > +/* add_function - adds a name to the list of functions, in order. */ > + > +void > +add_function (char *name) > +{ > + functList *p = (functList *)malloc (sizeof (functList)); > + p->functname = (char *)malloc (strlen (name) + 1); > + strcpy (p->functname, name); > + > + if (head == NULL) > + { > + head = p; > + tail = p; > + p->next = NULL; > + } > + else > + { > + tail->next = p; > + tail = p; > + tail->next = NULL; > + } > +} > + > +static void > +GenerateInitCalls (functList *p) > +{ > + while (p != NULL) > + { > + printf (" _M2_%s_init (argc, argv, envp);\n", p->functname); > + p = p->next; > + } > +} > + > +static void > +GenerateFinishCalls (functList *p) > +{ > + if (p->next != NULL) > + GenerateFinishCalls (p->next); > + printf (" _M2_%s_finish (argc, argv, envp);\n", p->functname); > +} > + > +static void > +GeneratePrototypes (functList *p) > +{ > + while (p != NULL) > + { > + if (langC) > + { > + printf ("extern void _M2_%s_init (int argc, char *argv[], char *envp[]);\n", > + p->functname); > + printf ("extern void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n", > + p->functname); > + } > + else > + { > + printf ("extern \"C\" void _M2_%s_init (int argc, char *argv[], char *envp[]);\n", > + p->functname); > + printf ("extern \"C\" void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n", > + p->functname); > + } > + p = p->next; > + } > +} > + > +/* ParseFileStartup - generates the startup code. */ > + > +static void > +ParseFileStartup (void) > +{ > + char name[MAX_FILE_NAME]; > + functList *p; > + > + while (PutChar (GetChar ()) != (char)EOF) > + { > + CopyUntilEolInto (name); > + if ((strlen (name) > 0) && (strcmp (name, "mod_init") != 0) > + && (name[0] != '#')) > + add_function (name); > + } > + GeneratePrototypes (head); > + printf ("extern"); > + if (!langC) > + printf (" \"C\""); > + printf (" void _exit(int);\n"); > + > + printf ("\n\nint %s(int argc, char *argv[], char *envp[])\n", NameOfMain); > + printf ("{\n"); > + GenerateInitCalls (head); > + GenerateFinishCalls (head); > + if (ExitNeeded) > + printf (" _exit(0);\n"); > + printf (" return(0);\n"); > + printf ("}\n"); > +} > + > +/* OpenOutputFile - shut down stdout and open the new mod_init.c */ > + > +static void > +OpenOutputFile (void) > +{ > + if (strcmp (NameOfFile, "-") != 0) > + { > + if (close (STDOUT) != 0) > + { > + ERROR ("Unable to close stdout"); > + exit (1); > + } > + OutputFile = creat (NameOfFile, 0666); > + if (OutputFile != STDOUT) > + { > + ERROR ("Expected that the file descriptor should be 1"); > + } > + } > +} > + > +/* CloseFile - flush and close the file. */ > + > +static void > +CloseFile (void) > +{ > +#if 0 > + fflush(stdout); > + if (close(STDOUT) != 0) { > + ERROR("Unable to close our output file"); exit(1); > + } > +#endif > +} > + > +/* CopyUntilEof - copies from the current input marker until ENDOFILE > + is reached. */ > + > +static void > +CopyUntilEof (void) > +{ > + char ch; > + > + while ((ch = GetChar ()) != ENDOFILE) > + putchar (ch); > +} > + > +/* CopyUntilEol - copies from the current input marker until '\n' is > + reached. */ > + > +static void > +CopyUntilEol (void) > +{ > + char ch; > + > + while (((ch = GetChar ()) != '\n') && (ch != (char)EOF)) > + putchar (ch); > + if (ch == '\n') > + putchar (ch); > +} > + > +/* CopyUntilEolInto - copies from the current input marker until '\n' > + is reached into a Buffer. */ > + > +static void > +CopyUntilEolInto (char *Buffer) > +{ > + char ch; > + int i = 0; > + > + while (((ch = GetChar ()) != '\n') && (ch != (char)EOF)) > + { > + Buffer[i] = ch; > + i++; > + } > + if ((ch == '\n') || (ch == (char)EOF)) > + Buffer[i] = (char)0; > +} > + > +/* IsSym - returns true if string, s, was found in the input stream. > + The input stream is uneffected. */ > + > +static int > +IsSym (char *s) > +{ > + int i = 0; > + > + while ((s[i] != (char)0) && (s[i] == PutChar (GetChar ()))) > + { > + GetChar (); > + i++; > + } > + if (s[i] == (char)0) > + { > + PushBack (s); > + /* found s in input string. */ > + return (TRUE); > + } > + else > + { > + /* push back the characters we have scanned. */ > + if (i > 0) > + { > + do > + { > + i--; > + PutChar (s[i]); > + } > + while (i > 0); > + } > + return (FALSE); > + } > +} > + > +/* SymIs - returns true if string, s, was found in the input stream. > + The token s is consumed from the input stream. */ > + > +static int > +SymIs (char *s) > +{ > + int i = 0; > + > + while ((s[i] != (char)0) && (s[i] == PutChar (GetChar ()))) > + { > + GetChar (); > + i++; > + } > + if (s[i] == (char)0) > + { > + /* found s in input string. */ > + return (TRUE); > + } > + else > + { > + /* push back the characters we have scanned. */ > + if (i > 0) > + { > + do > + { > + i--; > + PutChar (s[i]); > + } > + while (i > 0); > + } > + return (FALSE); > + } > +} > + > +/* FindString - keeps on reading input until a string, String, is > + matched. If end of file is reached then FALSE is returned, otherwise > + TRUE is returned. */ > + > +static int > +FindString (char *String) > +{ > + int StringIndex = 0; > + int Found = FALSE; > + int eof = FALSE; > + char ch; > + > + while ((!Found) && (!eof)) > + { > + if (String[StringIndex] == (char)0) > + /* must have found string. */ > + Found = TRUE; > + else > + { > + ch = GetChar (); > + eof = (ch == ENDOFILE); > + if (ch == String[StringIndex]) > + StringIndex++; > + else > + StringIndex = 0; > + } > + } > + return (Found); > +} > + > +/* GetNL - keeps on reading input from until a new line is found. */ > + > +static void > +GetNL (void) > +{ > + char ch; > + > + while ((ch = GetChar ()) != '\n') > + putchar (ch); > + putchar ('\n'); > +} > + > +/* GetChar - returns the current character in input. */ > + > +static char > +GetChar (void) > +{ > + char ch; > + > + if (StackPtr > 0) > + { > + StackPtr--; > + return (Stack[StackPtr]); > + } > + else > + { > + if (GetSingleChar (&ch)) > + return (ch); > + else > + return (ENDOFILE); > + } > +} > + > +#define MAXBUF 0x1000 > +static int Pointer = 0; > +static int AmountRead = 0; > +static char Buffer[MAXBUF]; > + > +/* ResetBuffer - resets the buffer information to an initial state. */ > + > +static void > +ResetBuffer (void) > +{ > + StackPtr = 0; > + Pointer = 0; > + AmountRead = 0; > +} > + > +/* GetSingleChar - gets a single character from input. TRUE is > + returned upon success. */ > + > +static int > +GetSingleChar (char *ch) > +{ > + if (Pointer == AmountRead) > + { > + AmountRead = read (CurrentFile, &Buffer, MAXBUF); > + if (AmountRead < 0) > + AmountRead = 0; > + Pointer = 0; > + } > + if (Pointer == AmountRead) > + { > + *ch = ENDOFILE; > + return (FALSE); > + } > + else > + { > + *ch = Buffer[Pointer]; > + Pointer++; > + return (TRUE); > + } > +} > + > +/* InRange - returns true if Element is within the range Min..Max. */ > + > +static int > +InRange (int Element, unsigned int Min, unsigned int Max) > +{ > + return ((Element >= Min) && (Element <= Max)); > +} > + > +/* PutChar - pushes a character back onto input. This character is > + also returned. */ > + > +static char > +PutChar (char ch) > +{ > + if (StackPtr < MAXSTACK) > + { > + Stack[StackPtr] = ch; > + StackPtr++; > + } > + else > + { > + ERROR ("Stack overflow in PutChar"); > + } > + return (ch); > +} > + > +/* IsSpace - returns true if character, ch, is a space. */ > + > +static int > +IsSpace (char ch) > +{ > + return ((ch == ' ') || (ch == '\t')); > +} > + > +/* SkipSpaces - eats up spaces in input. */ > + > +static void > +SkipSpaces (void) > +{ > + while (IsSpace (PutChar (GetChar ()))) > + putchar (GetChar ()); > +} > + > +/* SilentSkipSpaces - eats up spaces in input. */ > + > +static void > +SilentSkipSpaces (void) > +{ > + char ch; > + > + while (IsSpace (PutChar (GetChar ()))) > + ch = GetChar (); /* throw away character. */ > +} > + > +/* SkipText - skips ascii text, it does not skip white spaces. */ > + > +static void > +SkipText (void) > +{ > + while (!IsSpace (PutChar (GetChar ()))) > + putchar (GetChar ()); > +} > + > +/* SilentSkipText - skips ascii text, it does not skip white spaces. */ > + > +static void > +SilentSkipText (void) > +{ > + char ch; > + > + while (!IsSpace (PutChar (GetChar ()))) > + ch = GetChar (); /* throw away character. */ > +} > + > +/* PushBack - pushes a string, backwards onto the input stack. */ > + > +static void > +PushBack (char *s) > +{ > + int i; > + > + i = strlen (s); > + while (i > 0) > + { > + i--; > + PutChar (s[i]); > + } > +} > + > +/* IsDigit - returns true if a character, ch, is a decimal digit. */ > + > +static int > +IsDigit (char ch) > +{ > + return (((ch >= '0') && (ch <= '9'))); > +} > + > +/* GetName - returns the next name found. */ > + > +static void > +GetName (char *Name) > +{ > + int i; > + char ch; > + > + SkipSpaces (); > + ch = GetChar (); > + i = 0; > + while (!IsSpace (ch)) > + { > + Name[i] = ch; > + i++; > + ch = GetChar (); > + } > + Name[i] = '\0'; > +} > + > +/* FindSource - open source file on StdIn. */ > + > +static void > +FindSource (char *Name) > +{ > + if (close (STDIN) != 0) > + { > + ERROR ("close on STDIN failed"); > + } > + CurrentFile = open (Name, O_RDONLY); > + if (CurrentFile < 0) > + { > + perror ("failed to open file"); > + exit (1); > + } > + if (CurrentFile != STDIN) > + { > + ERROR ("Expecting file descriptor value of 1"); > + } > +}