head 1.19; access; symbols pkgsrc-2015Q3:1.18.0.8 pkgsrc-2015Q3-base:1.18 pkgsrc-2015Q2:1.18.0.6 pkgsrc-2015Q2-base:1.18 pkgsrc-2015Q1:1.18.0.4 pkgsrc-2015Q1-base:1.18 pkgsrc-2014Q4:1.18.0.2 pkgsrc-2014Q4-base:1.18 pkgsrc-2014Q3:1.17.0.44 pkgsrc-2014Q3-base:1.17 pkgsrc-2014Q2:1.17.0.42 pkgsrc-2014Q2-base:1.17 pkgsrc-2014Q1:1.17.0.40 pkgsrc-2014Q1-base:1.17 pkgsrc-2013Q4:1.17.0.38 pkgsrc-2013Q4-base:1.17 pkgsrc-2013Q3:1.17.0.36 pkgsrc-2013Q3-base:1.17 pkgsrc-2013Q2:1.17.0.34 pkgsrc-2013Q2-base:1.17 pkgsrc-2013Q1:1.17.0.32 pkgsrc-2013Q1-base:1.17 pkgsrc-2012Q4:1.17.0.30 pkgsrc-2012Q4-base:1.17 pkgsrc-2012Q3:1.17.0.28 pkgsrc-2012Q3-base:1.17 pkgsrc-2012Q2:1.17.0.26 pkgsrc-2012Q2-base:1.17 pkgsrc-2012Q1:1.17.0.24 pkgsrc-2012Q1-base:1.17 pkgsrc-2011Q4:1.17.0.22 pkgsrc-2011Q4-base:1.17 pkgsrc-2011Q3:1.17.0.20 pkgsrc-2011Q3-base:1.17 pkgsrc-2011Q2:1.17.0.18 pkgsrc-2011Q2-base:1.17 pkgsrc-2011Q1:1.17.0.16 pkgsrc-2011Q1-base:1.17 pkgsrc-2010Q4:1.17.0.14 pkgsrc-2010Q4-base:1.17 pkgsrc-2010Q3:1.17.0.12 pkgsrc-2010Q3-base:1.17 pkgsrc-2010Q2:1.17.0.10 pkgsrc-2010Q2-base:1.17 pkgsrc-2010Q1:1.17.0.8 pkgsrc-2010Q1-base:1.17 pkgsrc-2009Q4:1.17.0.6 pkgsrc-2009Q4-base:1.17 pkgsrc-2009Q3:1.17.0.4 pkgsrc-2009Q3-base:1.17 pkgsrc-2009Q2:1.17.0.2 pkgsrc-2009Q2-base:1.17 pkgsrc-2009Q1:1.14.0.24 pkgsrc-2009Q1-base:1.14 pkgsrc-2008Q4:1.14.0.22 pkgsrc-2008Q4-base:1.14 pkgsrc-2008Q3:1.14.0.20 pkgsrc-2008Q3-base:1.14 cube-native-xorg:1.14.0.18 cube-native-xorg-base:1.14 pkgsrc-2008Q2:1.14.0.16 pkgsrc-2008Q2-base:1.14 cwrapper-base:1.14 cwrapper:1.14.0.14 pkgsrc-2008Q1:1.14.0.12 pkgsrc-2008Q1-base:1.14 pkgsrc-2007Q4:1.14.0.10 pkgsrc-2007Q4-base:1.14 pkglint-current:1.14 pkgsrc-2007Q3:1.14.0.8 pkgsrc-2007Q3-base:1.14 pkgsrc-2007Q2:1.14.0.6 pkgsrc-2007Q2-base:1.14 pkgsrc-2007Q1:1.14.0.4 pkgsrc-2007Q1-base:1.14 pkgsrc-2006Q4:1.14.0.2 pkgsrc-2006Q4-base:1.14 pkgsrc-2006Q3:1.13.0.2 pkgsrc-2006Q3-base:1.13 pkgsrc-2006Q2:1.12.0.2 pkgsrc-2006Q2-base:1.12 pkgsrc-2006Q1:1.1.0.2 pkgsrc-2006Q1-base:1.1; locks; strict; comment @# @; 1.19 date 2015.11.25.13.29.08; author rillig; state dead; branches; next 1.18; commitid wTE9Uc9JWdmhBtKy; 1.18 date 2014.10.09.13.54.47; author wiz; state Exp; branches; next 1.17; commitid x2983HMt9cEs0xTx; 1.17 date 2009.06.13.06.33.35; author rillig; state Exp; branches; next 1.16; 1.16 date 2009.04.26.11.27.42; author rillig; state Exp; branches; next 1.15; 1.15 date 2009.04.26.11.00.17; author rillig; state Exp; branches; next 1.14; 1.14 date 2006.11.25.20.27.42; author rillig; state Exp; branches; next 1.13; 1.13 date 2006.07.02.09.47.17; author rillig; state Exp; branches; next 1.12; 1.12 date 2006.06.30.12.46.30; author rillig; state Exp; branches; next 1.11; 1.11 date 2006.06.30.12.34.44; author rillig; state Exp; branches; next 1.10; 1.10 date 2006.05.16.22.18.17; author rillig; state Exp; branches; next 1.9; 1.9 date 2006.05.11.09.05.33; author rillig; state Exp; branches; next 1.8; 1.8 date 2006.05.10.17.14.08; author rillig; state Exp; branches; next 1.7; 1.7 date 2006.05.10.17.01.44; author rillig; state Exp; branches; next 1.6; 1.6 date 2006.05.10.15.31.41; author rillig; state Exp; branches; next 1.5; 1.5 date 2006.05.10.13.52.49; author rillig; state Exp; branches; next 1.4; 1.4 date 2006.05.10.10.06.03; author rillig; state Exp; branches; next 1.3; 1.3 date 2006.05.10.08.17.25; author rillig; state Exp; branches; next 1.2; 1.2 date 2006.04.30.21.43.42; author rillig; state Exp; branches; next 1.1; 1.1 date 2006.02.26.23.38.07; author rillig; state Exp; branches; next ; desc @@ 1.19 log @Updated pkglint to 5.0 Notable changes include: * The whole code has been rewritten in Go * It is much faster, especially in recursive mode * The code has unit tests, providing examples of use * Some new explanations for existing warnings * Some adjustments to previous warnings @ text @ The &pkglint; type system One of the most notable additions to &pkglint; is the introduction of typed variables. Traditionally, in Makefiles, all variables have the type String. This prevents many useful checks from being done before executing the code. Up to 2004, &pkglint; already did some checks based on the value of the variables, but these checks had no common structure that could be described easily. History In February 2005, initial support for the &pkglint; type system has been added. Some of the common variables have been assigned types such as Boolean or Yes_Or_Undefined, which are the two common ways to represent boolean variables in pkgsrc. The list of typed variables has been moved from the &pkglint; code to an external file, makevars.map. Many more basic types have been added later. In October 2005, the type system has been extended to allow List of simple-type, which allowed to handle variables like DEPENDS and CFLAGS. One month later, enumeration types have been added, allowing the type of PTHREAD_OPTS to be expressed as List of { require native }. In May 2006, the definition and use of variables has been further restricted by introducing ACLs, which define the permitted operations (write, append, default, read, preprocess-read) depending on the current file. Syntax for defining types type ::= (list-type)? simple-type (acls)? list-type ::= ("List" | "InternalList") "of" simple-type ::= predefined-type | enumeration predefined-type ::= [A-Za-z][0-9A-Z_a-z]* enumeration ::= "{" (enumeration-item)* "}" enumeration-item ::= [-0-9A-Z_a-z]+ acls ::= "[" (acl-entry ("," acl-entry)*)? "]" acl-entry ::= acl-subject ":" acl-perms acl-subject ::= [.0-9A-Za-z]+ | "_" acl-perms ::= [adprs]* Semantics of the types The simple types in &pkglint; are either predefined types or enumeration types. A predefined type is used by its name. See for the list of predefined types. An expression of an enumeration type may have either of the enumeration-items as a value. It may not reference other variables. A list type can be constructed from a predefined type or an enumeration. It is not possible to construct lists of lists, since I have never needed that. There are two types of lists, called List and InternalList, which are described in the pkgsrc guide, the chapter about Makefiles. Access Control Lists Additionally to the data type, which specifies what a variable can contain, the ACLs define where the variable can be defined or used (this is called the ACL subject) and which operations are allowed (these are the ACL permissions). The ACL subjects are specified by the filename. For example, Makefile and buildlink3.mk are valid ACL subjects. Since some names occur over an over in pkgsrc, these can be abbreviated as shown in . The character * is a placeholder for zero or more arbitrary characters, like in the shell. The possible actions on a variable are shown in . ACL Subjects SubjectAbbreviationMakefilemMakefile.commoncbuildlink3.mkbhacks.mkhoptions.mkoany file*
ACL Permissions PermissionDescriptionaAppend to the variable using the += operator.dProvide a default value for the variable using the ?= operator.sSet the variable unconditionally using the =, := or != operator.uUse the value of the variable.pUse the value of the variable during preprocessing.
If a variable has no ACL definition at all, all operations are allowed on it. Otherwise exactly those operations of the first ACL entry whose subject matches the current filename are allowed. If no entry matches, nothing is allowed. For determining if a variable is used in the correct place, the filename is only one part of the whole decision. The other one is the context in which the variable appears. There are many factors that influence whether the variable is used correctly. The variable may be either used at preprocessing time or at runtime. Some variables are defined in bsd.pkg.mk and thus are not available until that file has been included. As this should always be the very last thing a package includes, it practically means that these variables are only available at runtime. The variable may appear as the whole right hand side of an assignment, as a single word, or even as part of a word. First, the types on the right and left side should be compatible. Second, some variables need to be quoted correctly, depending on whether they are part of a word or not. In shell commands, the variable may also appear as a whole word or as part of a word. This is similar to the case above. The variable may appear inside some sort of quotes. For some variables this is acceptable, as they are assumed to never contain special characters. For others it isn't. The various operators in conditional statements like .if may further restrict the valid values. For example, the OPSYS variable should only be compared to well-known operating system names. The exists() function should only be called on pathnames. The defined() operator only checks if the variable is defined and does not access its value. Future Directions Currently the ACLs only cover the user space of pkgsrc. They will be extended later to also check for valid variable definition and use in the pkgsrc infrastructure, as well as the user configuration file. For completeness, those variables that are intended to be specified on the command line will be added to the makevars.map file.
Predefined types There are many predefined types in &pkglint;, which are described below. AwkCommand An awk command. Currently nothing is checked here. BuildlinkDepmethod Must be either build or full. BuildlinkDepth This type is only intended for one variable, namely BUILDLINK_DEPTH, which is only modified in buildlink3.mk files. BuildlinkPackages The type of the variable BUILDLINK_PACKAGES. Like BuildlinkDepth above, this is only used in buildlink3.mk files. This variable has two different patterns to be modified. The first is to remove the current package from itself, and the second is to append the current package. This prevents a package from showing up twice in the list. Category One of the categories that a package may be placed in. The list of categories has been assembled manually when the type was introduced. There is no further agreement on which valid categories are valid, besides the top level directory names in pkgsrc. CFlag One word in a CFLAGS or CPPFLAGS variable. &pkglint; knows the flags starting with -D, -U, -I. Flags starting with -O, -W, -f, -g or -m are silently accepted since they are commonly used for the GNU compilers. As the pkgsrc framework does not know how to handle most of these flags, care should be taken. Comment The comment of a package. Dependency A simple dependency like foopkg>=1.0, foopkg-[0-9]* or foopkg-1.0. DependencyWithPath A dependency (see above), followed by a colon and a relative directory. For some packages, special variables like USE_TOOLS should be used instead of an explicit dependency. DistSuffix The value of the variable EXTRACT_SUFX. The difference in the name is intentional here, since EXTRACT_SUFX is a misnomer. DIST_SUFX or DIST_SUFFIX would be more appropriate. EmulPlatform An emulated platform consists of the operating system (in lowercase, as opposed to PlatformTriple) and the hardware architecture. Filename A filename, as defined in POSIX. This type further restricts the set of allowed characters. See also Pathname. Filemask A shell globbing pattern that does not contain a slash. See also Pathmask. Identifier In various places in pkgsrc, identifiers are used. This type collects the most common naming conventions. When you need a more specific check, you have to write your own check. LdFlag A flag that is passed to the linker. Flags starting with -L or -l are accepted, as well as some others that are assumed to be handled by the wrapper framework. Mail_Address Checks for a very restricted subset of RFC 2822. Message Messages are printed to the user as status indicators. As opposed to FreeBSD, they should not be quoted since they may be used in contexts where quoting should be done differently. Option An option from the PKG_OPTIONS framework. Options should not contain underscores. They should be documented in pkgsrc/mk/defaults/options.description. Pathlist A list of directories that are separated by colons, like the popular environment variable PATH. This type differs from the type List of Pathname in the character that is used as a separator. Pathmask A shell globbing expression that may include slashes. Pathname A pathname, as defined in POSIX. See also Filename. Perl5Packlist A common error has been to refer to INSTALLARCHLIB in the location of the packing list. Therefore no references to other variables are allowed. PkgName A package name should conform to some restrictions, since the filename of the binary package is created from it, which is then interpreted by pkg_add and the like. PkgOptionsVar I had once made the mistake of referencing PKGBASE in this variable, not knowing that PKG_OPTIONS_VAR is used during preprocessing, when PKGBASE is not yet defined. This type prevent that mistake from being done again. PkgPath A directory name that is relative to the top-level pkgsrc directory. This is only used in specifying specific packages in bulk builds. Despite its name, this type is more similar to RelativePkgDir than to RelativePkgPath. PkgRevision The package revision must be a small integer. The only place where this definition may occur is the package Makefile itself, as this variable says something about the individual package. There is no mechanism in pkgsrc for something similar to PKGREVISION that can be used in Makefile.common files. PlatformTriple pkgsrc has been ported to many platforms, all of which are identified using a triple of operating system, operating system version and hardware architecture. Readonly This type is used to mark a variable as being read-only to a package author. As this is not really a data type but an access restriction, it will disappear in the next version of the type system. RelativePkgDir A directory name that is relative to the package directory. Mostly used for dependencies. See also RelativePkgPath. RelativePkgPath A pathname that is relative to the package directory. It may point to either a regular file or a directory. See also RelativePkgDir. ShellCommand A shell command is similar to a List of ShellWord, except that additional checks are performed on the direct use of tool names or certain other deprecated shell commands. ShellWord A shell word is what the shell would regard as a single word. Stage In pkgsrc, there are phases, stages and steps. Especially for the SUBST_STAGE variable, this should always be one of the few predefined names, otherwise the whole substitution group will be ignored. Tool The pkgsrc tools framework contains very few plausibility checks. To prevent spelling mistakes, the list of valid tool names is loaded from the pkgsrc infrastructure files and compared with the names that are used in the USE_TOOLS variable. URL URLs appear in MASTER_SITES and the HOMEPAGE. If a MASTER_SITES group exists for a given URL, it should be used instead of listing the URL directly. UserGroupName User and group names should consist only of alphanumeric characters and the underscore. This restriction ensures maximum portability of pkgsrc. Userdefined Another instance of misuse of the type system. But it helps to catch some errors in packages. This type will disappear in the next version of the type system. See also Readonly. Varname Variable names are restricted to only uppercase letters and the underscore in the basename, and arbitrary characters in the parameterized part, following the dot. WrkdirSubdirectory The variable WRKSRC is usually defined with reference to WRKDIR. This check currently does nothing, and I don't know if it's worth to check anything here. WrksrcSubdirectory Subdirectories of WRKSRC can be used in CONFIGURE_DIRS and some other variables. For convenience, they are interpreted relative to WRKSRC, so package authors don't have to type ${WRKSRC} all the time. Yes This type is used for variables that are checked using defined(VARNAME). Their value is interpreted as true if they are defined, no matter if they are set to yes or no. YesNo This type is used for variables that are checked using defined(VARNAME) && !empty(VARNAME:M[Yy][Ee][Ss]). A value of no means no for them. YesNoFromCommand Like YesNo, but the value may be produced by a shell command using the != operator. Future directions Different interpretation of the same data types As explained above, there are internal lists and external lists in pkgsrc. But that is not the only attribute that a list can have. They also differ in the way they are defined, which files may access them, and what it means to append to append a value to it. For example, NOT_FOR_PLATFORM is a list that every file may append to without leading to unexpected behavior. Compare this with ONLY_FOR_PLATFORM, which should only be set in a single place throughout pkgsrc. Let's say in the package Makefile it is set to NetBSD-*-*, because this file's author knows for sure that the package is only usable on NetBSD. Now when some *.mk file from a dependency package adds DragonFly-*-* to it, the intent of the package Makefile is undermined by the dependency package, because now it is possible to build the package on DragonFly, too. The same problem arises with the various variables that can be either yes or undefined. They should always be chosen so that two definitions in different files don't undermine each other. A good example is USE_LIBTOOL, a bad example is NO_BUILD. TODO: What are the general properties of good and bad variables? How can it be decided of which kind a certain variable is? For most lists, the only valid operation is to append something at the end. Therefore it is good practice to warn if a list is assigned using another operator that +=. For SUBST_CLASSES this fits perfectly. But for SUBST_FILES.* it doesn't. Usually all occurences of a SUBST_FILES.* variable occur in the same file, and there should be no other file modifying these variables. Therefore it is better to use the = operator for the first of the assignments.
@ 1.18 log @More SVR4_PKGNAME cleanup. @ text @d1 1 a1 1 @ 1.17 log @Documented the most recent change. @ text @d1 1 a1 1 a405 6 SVR4PkgName When converting pkgsrc packages to Solaris packages, the package name is restricted to 9 characters, of which five remain for the package itself. @ 1.16 log @Documented the recent addition of the PkgPath type. @ text @d1 1 a1 1 d279 5 @ 1.15 log @Added tags so the document validates again. @ text @d1 1 a1 1 d361 7 @ 1.14 log @Fixed some typos in the pkglint documentation. Reported by OKANO Takayoshi in a private mail. @ text @d1 1 a1 1 d157 1 a157 1 The variable may be either used at preprocessing time d162 1 a162 1 variables are only available at runtime. d164 1 a164 1 The variable may appear as the whole right hand side d168 1 a168 1 depending on whether they are part of a word or not. d170 1 a170 1 In shell commands, the variable may also appear as a d172 1 a172 1 above. d174 1 a174 1 The variable may appear inside some sort of quotes. d177 1 a177 1 isn't. d179 1 a179 1 The various operators in conditional statements like d186 1 a186 1 value. @ 1.13 log @Updated pkglint to 4.66. This change includes all the things I thought of during the freeze of 2006Q2. Some variables have disappeared from pkgsrc without notice. Marked them deprecated to help the package authors at least a bit. Renamed some ACL abbreviations in makevars.map and adjusted the variable definitions. Added the command line options -Dtrace, -Dunchecked and -Dunused. Some variables may contain unexpected white-space and therefore should not be used in .for loops. The -Dmisc option replaces the --verbose option (and the log_info subroutine), which does not exist any longer. This eliminates all instances of "OK:" from the output, which I didn't like from the beginning. The -Dmisc option also takes over many warnings that have been issued by --debug before. Improved the check for absolute pathnames. Especially, everything that follows ${DESTDIR} or $(DESTDIR) in a Makefile is considered an absolute pathname. This reveals many wrong uses of DESTDIR (as defined by the GNU coding standards), for example $(DESTDIR)/$(prefix), which should be $(DESTDIR)$(prefix) instead. Almost every use of a make(1) variable is checked for spelling mistakes. Before, only the definitions of variables have been checked. Restricted the use of variables to specific files, which are defined in makevars.map. This catches especially buildlink3.mk files with unexpected side effects. In shell commands, neither "echo" nor "echo -n" or "${ECHO} -n" should be used. Since the INSTALL_*_DIR commands can only handle one directory at a time, suggest to use INSTALLATION_DIRS instead. Greatly improved the checks for dependency specifications, especially to find foo-*, which should rather be foo-[0-9]*. Fixed the incorrect handling of LICENSE_FILE (now using $line->text instead of $line). Improved the wording of the "plural names" warnings, so that for known variables it is "The += operator should only be used with lists." now. In buildlink3.mk files the uppercase and lowercase names of the package should correspond with the package name. This catches many copy-and-paste mistakes. Fixed many null pointer exceptions as well. In addition, every buildlink3.mk file needs a definition of BUILDLINK_API_DEPENDS. In patch files, absolute pathnames and unportable macro names are checked not only in added lines, but also in the context lines. In the pkgsrc root directory and the category directories, the Makefiles are checked like every other Makefile, too. Fixed the place where the global variables for the package context are defined and later undefined. Variables that are mentioned in EVAL_PREFIX may be used in the current file and are not flagged as "used but not defined". When parsing shell words in Makefiles, recognize $<, $@@, $^ and $/. (The latter is used extensively by openoffice to represent a directory separator.) Fixed some minor bugs: * $makevar had been defined unintentionally by using the -> operator. @ text @d1 1 a1 1 d194 1 a194 1 space of pksrc. They will be extended later to also d320 1 a320 1 pkgsrc/mk/default/options.description. @ 1.12 log @SUBST_CLASSES and SUBST_FILES.* are very different. @ text @d1 1 a1 1 d74 3 a76 4 Enumeration types are defined by writing a {, followed by the enumeration items, followed by a }. The enumeration items are separated by space characters. d488 4 a491 1 d537 1 @ 1.11 log @In some cases variables of the same data type are interpreted differently, which may lead to problems. @ text @d1 1 a1 1 d523 12 @ 1.10 log @bsd.options.mk may set PKG_OPTIONS. @ text @d1 1 a1 1 d489 35 @ 1.9 log @Some ideas about the contexts in which variables may be used. @ text @d1 1 a1 1 d185 3 a187 1 pathnames. @ 1.8 log @- ACL subjects may contain * as a placeholder. @ text @d1 1 a1 1 d150 39 @ 1.7 log @The := or != operators can be used for unconditional assignment, too. @ text @d1 1 a1 1 d103 3 a105 1 />. The possible actions on a variable are shown in *.mkk any file_ @ 1.6 log @- Improved ACL definitions in makevars.map. - Added checks for deprecated and nonexistent licenses. (suggested by gdt) - Added detection for /foo/s/bar/baz/ sed command that appears without a leading "-e" in a SedCommands variable. (suggested by wiz) @ text @d1 1 a1 1 d133 2 a134 1 variable unconditionally using the = @ 1.5 log @ACL entries are separated by a comma and optional white-space, since that looks nicer. @ text @d1 1 a1 1 d116 1 @ 1.4 log @Rewrote the section on ACLs. Now I must adjust the implementation to this specification. @ text @d1 1 a1 1 d48 1 a48 1 type ::= list-typeopt simple-type aclsopt d58 1 a58 1 acls ::= "[" (acl-entry)* "]" @ 1.3 log @- Added the class PkgLint::Type. - Added the -Wacl command line option, which is disabled by default. - Extended the type definitions in makevars.map by ACLs, which specify in which files the variables may be defined. - Trailing white-space in DESCR files can be fixed automatically. - Use of the $$ shell variable is not flagged as "strange" anymore. - Added ACL-based checks for variable definitions. - PKGREVISION should not be set to 0. - Improved the diagnostics text for RESTRICTED. - Added the types Unchecked and Version. - Dashes are allowed in library names in wrapper reordering commands. - More than one DISTFILES definition is allowed in the variable ordering check. @ text @d1 1 a1 1 d12 1 a12 1 To that time, &pkglint; already did some checks based on d37 5 d48 4 a51 2 type ::= ("List" | "InternalList") "+"? "of" simple-type | simple-type d57 5 d85 56 a140 1 chapter about Makefiles. d142 15 a156 7 If the List or InternalList is followed by a +, which restricts the valid operations on a variable of that type. The only allowed operations are setting the list to a commented empty value, for example # none, or appending to the list, using the += operator. d158 1 a444 49 Future directions The framework for defining data types in the makevars.map file is insufficient. It does not allow ACLs that specify which variables may be read or written by the various actors in pkgsrc. At the moment, the data type and the permissions are intermixed (see type Readonly). To overcome these design flaws, I will create a new type system for &pkglint; that is based on the current one, but provides ACLs to define the permitted operations on each variable. Each ACL entry is then a combination of an actor with an operation. ACL Actors ActorDescriptionpackageThe package authorsystemThe pkgsrc infrastructurebl3buildlink3.mk and builtin.mk filesuserThe pkgsrc user via mk.confcmdlineThe pkgsrc user via the command line
ACL Operations OperationDescriptionwriteCreate a variable or overwrite the valuecolonAssign using the := operatorappendAppend to a listdefaultProvide a default value for a variablereadUse the value when executing the shell commandsreadppUse the value during preprocessing
@ 1.2 log @List! has been replaced by InternalList. @ text @d1 1 a1 1 d407 1 @ 1.1 log @Added the book ``Design and implementation of pkglint''. @ text @d1 1 a1 1 d43 1 a43 1 type ::= list-variant "of" simple-type a44 1 list-variant ::= "List" "!"? "+"? d69 9 a77 10 since I have never needed that. When defining a list type, the List keyword may be followed immediately (that is, no white-space) by a ! or a +. A ! means that the list is an internal list, as opposed to an external list. Most lists are external lists, so this has been chosen as the default value. The differences between these two types are described in the pkgsrc guide, the chapter about Makefiles. A + restricts the valid operations on a @