From: "Martin Liška" <mliska@suse.cz>
To: Gaius Mulley <gaiusmod2@gmail.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH v2 16/19] modula2 front end: bootstrap and documentation tools
Date: Mon, 7 Nov 2022 14:47:02 +0100 [thread overview]
Message-ID: <50b276a7-3a18-d405-b672-eecb5067f5de@suse.cz> (raw)
In-Reply-To: <87r0yesygv.fsf_-_@debian>
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 <gaius@glam.ac.uk>.
> +#
> +# 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
> +# <http://www.gnu.org/licenses/>.
> +#
> +
> +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
> +<http://www.gnu.org/licenses/>.
> +"""
> +
> +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
> +<http://www.gnu.org/licenses/>.
> +"""
> +
> +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 <https://www.gnu.org/licenses/>.
> +"""
> +
> +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 <gaius.mulley@southwales.ac.uk>.
> +#
> +# 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 <gaius.mulley@southwales.ac.uk>.
> +#
> +# 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 <gaius.mulley@southwales.ac.uk>.
> +
> +# 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 <gaius@glam.ac.uk>.
> +
> +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
> +<http://www.gnu.org/licenses/>. */
> +
> +
> +#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 <modulelistfile>\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 "
> + "<modulelistfile>\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 "
> + "<modulelistfile>\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");
> + }
> +}
next prev parent reply other threads:[~2022-11-07 13:47 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-10 15:31 [PATCH] 16/19 " Gaius Mulley
2022-10-13 9:12 ` Martin Liška
2022-10-14 12:10 ` Gaius Mulley
2022-11-07 13:09 ` [PATCH v2 16/19] " Gaius Mulley
2022-11-07 13:47 ` Martin Liška [this message]
2022-11-08 13:22 ` Gaius Mulley
2022-11-24 11:53 ` Martin Liška
2022-11-24 14:30 ` Gaius Mulley
2022-11-25 16:25 ` Martin Liška
2022-11-25 17:10 ` David Malcolm
2022-11-27 16:51 ` Gaius Mulley
2022-10-20 12:42 ` [PATCH] 16/19 " Martin Liška
2022-10-28 13:05 ` Gaius Mulley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50b276a7-3a18-d405-b672-eecb5067f5de@suse.cz \
--to=mliska@suse.cz \
--cc=gaiusmod2@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).