![]() |
What qsg is, how it works, command-line options, the scripting language and the library. |
![]() |
Although any arbitrary shell pipeline can be used as a
script generator, the primary ones used are qsg |
![]() |
qsg is several things at once. First and foremost, it is a script generator. Beyond that, qsg is a small programming language designed to generate output which will function as input to another process (usually qsh or mimk). Using qsg on simple files is probably the best way to learn it, as in: % cat > tmp if @argvYou can try out the qsg standard library scripts directly from the command shell, as in: % qsg -c hanoi 5 1: move ring 1 from this one to that one 2: move ring 2 from this one to over there 3: move ring 1 from that one to over there 4: move ring 3 from this one to that one ... % qsg -c commands example.c #include mimkvars.qh #include deps.qh Objects:V: example.o example.o:P: _S_(example.c) _Touch_(cc) _T_cc -c _F_cc _F_cc_c _F_cc[example]qsg has a variety of applications. For example, this guide itself is written in qsg using the html.qsl qsg library ![]() |
||
A Typical qeffile |
Every directory in which a construction occurs must have an associated file called qeffile (or qeffile2). The second section of that file, the part following the Begin line, is usually a qsg script. Everything that applies to standard qsg scripts applies also to the script portion of a qeffile. The most common qeffile looks something like this: BeginWhen the Begin line does not have arguments, the value of the @DefaultBeginLine is used. If it has not defined, "qsg -M" is used. Typically, fifty percent of qeffiles use the default value. The -M argument specifies that the basenames of the
directory's source files
|
![]() |
The qsg components of QEF product consists of the following tools and files: |
||||||||||||||||||
qsg | The general-purpose script generator, with a built-in compiler and interpreter. | ||||||||||||||||||
lib/qsg/std.qsl | Archive of standard qsg scripts in compiled form. qsg and qsgdump search this library for requested scripts. Additional libraries, such as a project specific library, can be created as required. | ||||||||||||||||||
lib/qsg/*.qsl |
There are nine additional qsg libraries provided in the
<qtree>/lib/qsg directory.
These are:
To get a listing of the scripts provided by a particular library use: % qsgdump -L -llib -l-NThe -l-N flag are to suppress the automatic loading of the standard library and any libraries specified by @QsgLibs. To view the source for any script within a library, use: % qsgdump -S -llib scriptTo see a script's summary, use -X instead of -S. |
||||||||||||||||||
qsgcomp | Compiles its argument script and outputs object code. Used to create object files put into script library. | ||||||||||||||||||
qsgdump | Compiles argument scripts (if necessary) or extracts from library and dump code (by default), summary (-X flag), or source (-S flag). | ||||||||||||||||||
x-qsg |
An eXplanatory database describing features of the qsg system.
To retrieve a list of the major items in the database use:
% x-qsg x-qsg : qsg and its support library eXplanatory D.B. qsg-intro : introduction to qsg qsg-tools : qsg tools and files qsg-M : that qsg -M flag qsg-variables : variables in qsg argv : arguments to a qsg scriptTo retrieve the information of a particular item, such as qsg-M, use:/lib/qsg/std.qsl : the standard qsg library qsg-sfxmaps : qsg mapping of suffix to script controls qsg-scripts : list of standard qsglib scripts qsg-input : qsg input conventions and the escape qsg-syntax : qsg keywords and syntax qsg-listops : the qsg postfix % x-qsg qsg-M qsg-M : that qsg -M flag As has been mentioned in qsg-intro, about 50% of the Begin lines are: Begin qsg -M or its equivalent: Begin ...Appendix G: The QEF Specialist's Reference Card contains four items extracted from x-qsg for quick reference. These are:
|
![]() |
The synopsis of the qsg command is: qsg [qsg-options] [--] [script-options]The "--" is required if the first script option begins with a `-'. The command: % qsg -x qsg [-xVMmqrST] [-C[mp]] [-a file] [-f script]will output a brief description of all the flags and options. Typically, qsg is called with one of the following options:
The qsg -M command suffices for the majority of software constructions. Using the list of source files (usually the sls produced srclist._), and the directory's qeffile as the input script, it builds the construction in the current directory. The qsg -f <file> option is usually used to run a script that is not contained in a script library, as in: % qsg -f file -- argumentsTypically, you run a script in this fashion until it is thoroughly debugged, at which time you place the script in a library. The qsg -c <command> option is usually used directly from the command line, as in: % qsg -c hanoi 3 # run 3 ring tower of hanoiFor the -c option, the balance of the arguments are taken to be arguments to the script, thus the -- is not required. |
||||||||
qvrs variables used by qsg |
qsg scripts can access any qvrs variable or expression using
the functions @(qvrs variable),
@(qvrsexpr expression),
or the short form of the qvrs function, @{variable},
however, four variables are used by qsg itself.
These are:
|
||||||||
Running a Library Script |
To run a qsg library script, you simply need to know its name and the flags and arguments it accepts. The result of running a library script is almost always another script to another process. That is, scripts are both the input to and output from qsg. Running the qsg script to create a library or program, for example, does not directly create the library or program. Rather, it creates a mimk script to accomplish this. To actually create the program or library, you must interpret the generated script using the appropriate back-end (e.g. mimk). This processing, that is the invocation of qsg to create the script, and mimk to interpret it, is all managed by qef. For a list of the scripts available in the qsg library, use the command: % x-qsg -L \*scripts For a detailed description of any particular script, use the command: % x-qsg <scriptname> |
![]() |
The standard qsg library consists of seventy five scripts designed to handle the most common tasks involved in software production. We recommend that you do not modify any of these scripts, but we encourage you to examine them for useful constructs. To get the source for a specific library module, use: % qsgdump -S script Some of the most important library scripts are described in Chapter 7.5: The Construction Script. A project might need to extend the range of facilities offered by std.qsl to deal with languages and/or file types not currently handled. While you could add new scripts to the standard qsg library, we recommend that you create new a new project or organization specific qsg library instead. This is best done as follows:
|
![]() |
A qsg script has the following structure: summary <flag_spec> [-] <argument_spec> <explanatory text> endsummary # zero or more procs proc <name> <flags> [-] <arguments> ... endproc <script> Both the summary and the procedure definition(s) are optional. The summary defines the flags and their types accepted by the script. The summary/endsummary keywords can also bracket a text description, displayed by qsgdump -X. The proc keyword begins a procedure. Procedures are local to the defining script. The arguments specify the name of the procedure and the flags, if any. The procedure terminates with endproc. The [-] in the synopsis is literal (i.e., not an optional `-'). A `-' is used to terminate flags if the first argument begins with a `-'. See *defs-kws(x-qsg) for more information on the summary and proc keywords. The actual script consists of keywords, variables, and arguments. Variables are lists of words. A variable's value may be incorporated into an argument list by placing the @ character before it: @L is the value of the variable L. Literal spaces, tabs, and `@'s can be embedded in an argument list by preceding it with a `@'. The @ character can also be used to escape newlines to split long lines. Any list can be modified by a post-fix |
![]() |
The following is a contrived qsg script that contains examples of
some of the syntactic forms or the language, with comments to
explain their use and semantics.
summary [-ab] [-p parm] [-l list]+ [-o[opt]] [-] @ arguments ... short optional description -a a boolean flag -- variable aFlag contains value -b another flag -p parm value assigned to pParm -- only one allowed second instance will raise fatal error This description should include the default. -l list+ values assigned to lParm -- multiple instances allowed -o[opt] optional value -- oOpt
|
![]() |
qsg variables come in three flavours: local, global, and first-time
switches.
Local and global variables are lists of white space separated elements.
An `@' escaped space, tab, or `@' can be used to embed literal
spaces, tabs, or `@'s in a list element,
although they are converted to 037, 035, and 036 respectively.
The encoded forms are converted to the normal form on output.
Local variable names are one of more alphanumerics or underbars, the first of which cannot be a digit (i.e., the same as C modulo the `$' allowed by some C compilers). Global variable names can be any normal printable unsigned ASCII character greater than a space (i.e., bang to tilde), however use of `(' or `)' will make it awkward to retrieve the value using the literal name. First time switch names can also be any sequence of printable characters excluding white space (one can use escaped spaces and tabs if really necessary). The local variables are local to the current instance of the script or proc. When a script or proc is invoked, the flag processing then will set any specified flag's variable. The simple -X flag's variable (e.g., XFlag) is set to 0 or 1 depending on whether or not the flag was specified. The argv variable (which is always defined) is set to the arguments of the call after the flags and options. All other local variables are set to the empty list. Global variables are, obviously, global and are accessible to any script or proc, as are first time switches.
Global variables are set or modified using gset, gappend, gpop, and gprepend. The latter two functions are often used to implement stacks. In addition to the keywords, the special expansion @[/List], as in: ... @[/ Example example value]sets the global variable named by first word of the List (e.g., Example) to the balance of the list (e.g., example value). A global variable's value may be retrieved using @(g name) or its alias @(global ...). First-time-switches are used to prevent processes from being done a second time such as the processing for a source file or the output of the include of a header file. A 1st time switch can be set using the keyword set1st or the test and set function 1stset as in: if @(1stset switch-name) # switch-name was not previously set but it is now # ... first time only code else # 1st time switch was set previously # 2nd and subsequent time code fiA first time switch can be tested without setting it using the function @(notset name) which returns 1 (0) if the 1st time switch name wasn't (was) previously set. |
![]() |
Frequently, as discussed in Section 4, a project can benefit from
having its own qsg scripts to supplement or override those provided
by the standard qsg libraries as listed in Section 2.
The creation and use of such a library is described in
Section 4 and project.qsl(x-qmisc).
This section briefly discusses some of the principles that should be followed in developing new scripts that will conform to the normal style and form of the standard scripts. |
qsg-scripts(x-qsg) | This item lists the standard scripts. It should be reviewed as it is likely that there is an existing script that is similar to the script that you need to create. |
qsl_init |
Your library should have a script called qsl_init.
This script is invoked when your library is loaded.
It is typically used to bind scripts to suffixes, initialize
global variables such as the target keys, etc.
To view the source for the standard library's qsl_init, use:
% qsgdump -S qsl_init |
Summaries |
All scripts should have complete summaries giving the synopsis, a short
description, descriptions of all the flags (including their defaults
if relevant), and supplementary notes.
These summaries can be converted into an x_db database
if desired, but in any case they can be retrieved using:
% qsgdump -X script |
Types of Scripts | The qsg-scripts(x-qsg) item lists the standard scripts, partitioning them into construction, command, make object, and support scripts. When creating new scripts, attempts should be made to make those scripts resemble existing scripts in their interface and purpose. Scripts should use the support scripts as much as possible. The more important support scripts are described briefly below. |
Conventions |
Command scripts should be designed to take multiple argument
files and support much the same -cdLTv flags as the other command
scripts ![]() |
cmds_X | Scripts called cmds_X are used to process command *.X files and files with suffixes mapped to it using qsgcmdproc(x-qsg). A prime example of such as script is cmds_xdb which should examined as a prototype. Such scripts should process all its argument files creating recipes to create all intermediate and installed files and the appropriate target, item, and remove directives. |
mkobj_X | Scripts called mkobj_X are used to process *.X files and *.sfx files for which mkobj_sfx has been mapped to mkobj_X (usually in the qsl_init file) using qsg keyword mapscript or by setting @QsgMap[script] in a qvrs file. |
![]() |
The following scripts are provided by the standard library for use by other scripts. |
mkobj | This script is used to output commands to construct objects. It outputs the qef directives to create a File's object file (e.g., File.o), its assembler file (e.g., File.s), its cpp output (e.g., File.o). |
generic | This qsg script is used to output qef directives and recipes to build and optionally install a file with a specified recipe. This script is commonly used when the file's processing is non-standard. finstall is invoked to install the file if the -d flag is specified. |
target |
target file description outputs the qef #target line:
#target file descriptionbut only if there has not been a previous output for the same target. |
item |
item file1 file2 ... outputs the qef #item line:
#item file1 file2 ...but only if there has not been a previous output for the arguments. #target and #item lines are output by qef when the -Ptargets option is specified. |
rmfiles | This script outputs #rm{obj,inst,objpat,instpat} directives to remove the named or pattern matched files when one of the Remove* qef directives. |
putdeps & strdep | These scripts are used to output dependencies. putdeps is for prerequisite files whereas strdep is for strings. A string dependency will be stored in the history file. If the string dependency's value is changed, the target will be deemed out-of-date. String dependencies are normally used to store values that are not part of the recipe but will be used by the recipe's processes (e.g., an environment variable). |
![]() |
The qsg libraries misc and dtree
are a rich source of example scripts for a variety of languages.
To get a list of the scripts for these libraries use:
% x-qsg -L \*dtree_qsl \*misc_qslTo retrieve the source for a specific script, use: % qsgdump -llib script |
![]() |
We should not leave this chapter without a brief discussion of
the use of qsg to produce and manage this guide.
qsg, despite being are fairly simple language, is exceedingly
useful and no example is probably better than the role that qsg
plays in producing this guide both in its web and printed forms.
This text is written in qsg using the html library, which will be replaceable by an XML library in the future. This permits the use of variables such as @QSG which has been set to "@<tool qsg>" which will be translated into: <a href="appendix-E.html#qsg"><i>qsg</i></a>that is: qsg. Chapter, section, and labels headings appear as: chapter -inum @(flags pn) Title ... @# -p and -n flags # are previous and next links section title ... label title ...The example commands that appear some 350 times, for example: % qsg -c hanoi 3 # run 3 ring tower of hanoiare encoded as "@<cmd command # comment>". A -t flag is used if the command is to be linked to an entry in Appendix E. The @<cmd ...> script takes care of outputting the <pre>, the links, the font changes, etc. The text is just entered using the <<...>> form as in: << ... The text is just entered using the ... ><label Command In Middle of Output More text, some in @<b bold> ... ... >>So much for the source. The qeffile contains in part: gset PageMap @(call readlist @(findfile page.map)) if @(option PrintVersion) qsg2htm @argv else qsg2htm -d @{_DestDir_}/pages @argv fiThe page.map file contains the mapping of source file names (e.g., c080.qh) to section names (e.g., chapter-09.html). The qvrs option PrintVersion is used to suppress installation of the galley versions and suppress the links in the pages. The qsg2htm script will generate mimk dependencies and recipes for each of the source files, such as: c080.html:P: _S_(c080.qh) _DestDir_/lib/qsg/guide.qsl \ <qtree>/lib/qsg/html.qsl qsg -lguide -o c080.html -c _S_(c080.qh) \ -p chapter-08.html -n chapter-10.html #rmobj c080.htmlThe web versions are produced and installed using the same mechanism in a sibling directory using a spliced source path. Note that Appendices E through H are generated by x_db databases queries processed by qsg to produce HTML representations and the embedded links. Yet another qsg script is used to invoke netscape -remote commands to produce the PostScript versions of the pages. The PostScript files are then read by still another qsg script to modify the clipping box, insert page headers and footers that incorporate the section titles and page numbers and produce the page numbers mappings to be used in the table of contents and keyword index, also the produced by qsg scripts. Finally qsg scripts are used to create the installation packages and book production forms. Hence a single qef command will install the web pages, produce the book form, create the distribution package, and do the Chapter 10: file system integrity check via the simple application of a few qsg scripts. For your edification, the frequently referenced hanoi source is listed below for those who have not as yet installed the Q-Tree: summary [-] n [from to spare] run the towers of hanoi for N rings N number of rings to be moved from name of origin tower to name of target tower spare name of spare tower Well why not? If names of towers not provided, default names used. This script is provided for illustration and testing. endsummary proc hanoi [-] if @argv qsg is a remarkably useful little tool and it is fun to use. |
c080.qh - 1.34 - 00/05/30 |
![]() ![]() ![]() ![]() ![]() |