Please enable JavaScript to view this site.

A-Shell Reference

Updated February 2022

The List File compiler option—/LF for COMPIL.LIT, -lf for the standalone compiler—generates a consolidated list file showing all of the source code, with all of the ++INCLUDE files merged in. The list file is known as the "LSX file" (LiSt with indeX), is named <prog>.LSX, and is normally created in the same directory as the main program source, subject to the LSX_FSPEC pragma. Some of its attributes and uses are detailed in the comments below.

LSX Header

The LSX header includes details indicating how the program was compiled, and stats allowing you to be sure of a match between a particular pair of LSX and RUN files.The new header looks like this:

LSX >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Main Source : C:\VM\MIAME\DSK2\205170\apvch.bp

  Stats     : 442-203-632-231  25-Feb-22 14:33:35  259890 bytes

Object      : C:\VM\MIAME\DSK2\205170\apvch.run

  Stats     : 247-540-225-666  26-Feb-22 16:25:18  208514 bytes

Compiler    : 6.5(965)

  Switches  : /av /i /x:2 /lf /px /m

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

The top two lines provide the filespec, hash, last modification time and size of the main source module. The next two lines provide the same details for the object of the compilation (RUN, SBX, LIT). The last two lines are the same as in previous LSX versions, identifying the compiler version and switches.

Note that the compiler edit number is independent of both the A-Shell edit number and the version of COMPIL.LIT. To display the compiler edit number of the compiler embedded in A-Shell, enter COMPIL at the dot prompt without and arguments. For the standalone compiler, execute compil -about.

 

Standalone Recompilability

Since the LSX file contains all of the source code merged in from all the ++INCLUDE statements, it effectively captures the entire state of the source code at the time it was compiled, and thus provides an easy way to archive the source corresponding to a particular RUN or SBX module released. The top of the LSX file indicates the compiler version and switches, which you can use to regenerate the compiled output directly from the LSX file. For example, we can recompile the LSX with above header as follows:

.compil apvch.bp/av/i/x:2/px/m

Note that we don't need the /lf switch, but if it was included, a new list file will be created with a .LSY extension.

Also note that you can make minor edits to the LSX file and recompile it, perhaps to fix a minor bug in an older version of a program which has since undergone many changes that you don't want to introduce along with the bug fix. The only trick here is that the compiler expects every line of source code to be prefixed with the six digit location counter (see below) followed by two spaces, which you will need to manually add to any lines you add. However, this is just a syntactic formality; the compiler does not care about the value of the location counters in the LSX file, so you can just set them all to a dummy value like 000000 or 999999.

 

++INCLUDES

++include files are inserted into the consolidated LSX file with a header and footer to help you navigate the code. The header looks like this...

00f245  ++include'once bas:harvestdb.bsi

! DSK0:HARVESTDB.BSI[7,6] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< <77_6>

The <##_#> suffix at the end of the header indicates sequential file number and the nesting level. So in the above example, this is the 77th file opened so far (1 main and 76 include files), and we are now nested 6 levels deep.

At the end of the include file, a footer is inserted like this...

! >>>>>>>>>>>>>>>>> (harvestdb'bsi) ^> c:\vm\miame\dsk0\007006\prdlmt.bsi <75_5>

The name of the include file that we are returning from is in parentheses, followed by the full native spec of the file we are returning to (i.e. the one that contained the ++include that we just processed), followed by the <file#_level> indicator.

When a file include directive is skipped (e.g. ++include'once was specified and the file was already included), instead of the normal ++include file expansion, the LSX contains only a note as in the following:

00f245  ++include'once sql:sql.def

! Skipping sql.def (already included)

 

Location Counters

The LSX file contains the location counter for each line of the source code, providing a way to located the source corresponding to ASB errors. Traditionally programmers used line numbers for this purpose, but line numbers are cumbersome to deal with, cluttering up the source code, requiring renumbering utilities and management schemes to avoid duplicating line numbers in ++INCLUDE modules, making the RUN modules larger and adding to the execution overhead. In ASB they have mostly been deprecated in favor of location counters, which require no additional overhead or effort, other than to keep a copy of the LSX files corresponding to the compiled programs for cross-reference purposes.

The standard ASB error messages contain the location counter automatically, but if you are trapping errors yourself, you can retrieve the location counter using the ERR(8) function. You can also use the .LOCATION Dot Variable to retrieve the current location file, independent of error processing; see History notes below. Because it takes effort on the part of the user to write down and report error messages faithfully, and/or effort by the programmer to programmatically track them, you may want to take advantage of the built-in BASERR TRACE—by adding TRACE=BASERR to miame.ini—which results in all ASB errors, whether trapped or not, being logged to the ashlog.log file along with their location counters.

Note that by convention, location counter values are displayed in hex within internal error messages, log messages, LSX file, etc. But since the PRINT statement only outputs in decimal, you will need to use a function such as MX_OCVT or the function Fn'Dec2Hex$() in SOSLIB:[907,11] to convert the ERR(8) or .LOCATION values to hex, e.g. PRINT Fn'Dec2Hex$(ERR(8)).

Also note that because the LSX file only shows the location counter at the start of each source line, while an error might occur at a location in the middle of a source line, the location counter reported for an error may not necessarily match any location counter shown in the LSX file. For example, consider the following LSX excerpt:

003337       ELSEIF (dlg'ashdevinf_cntlsup_ary(x).gen'type = 5) THEN

00334f           menucntl = dlg'ashdevinf_cntl_ary(x)

00335b           IF (ABS(menucntl.clickcode) = ABS(click)) THEN

003369               fn'dlg'ashdevinf_clickcode2pointer = x

003371               EXIT

003375           ENDIF

003375

003375 !     comment bla bla bla

003375       ENDIF

003375   NEXT x

 

If the value of (x) in the second line generates a subscript out of range error (ASB error 8), the location counter reported for the error will probably be somewhere between the location given for the start of the line (334f) and the location for the start of the next line (335b). So to locate the error, you will just have to scroll through the LSX to find the pair of lines that bracket the error location.

The above example also illustrates the fact that many source lines do not increase the location counter at all, since they don't generate any executable code. The last 5 lines shown all have the same location counter, 3375.

 

Auto-Mapped Variables

If you don't use the /M switch, which reports un-mapped variables as errors, the compiler will automatically generate MAP statements for any such variables, and these will be listed near the bottom of the LSX file as follows:

MAP1 AUTO'MAPPED'VARS

    MAP2 COMMON'RKEY,F,6

    MAP2 COL'X,F,6

    MAP2 COPIES,F,6

 

This explicit listing provides a relatively easy way for you to come in from the figurative cold—of living with the subtle errors introduced by inevitable typos—to take advantage of the compiler's ability to point out those typos to you before they become bugs. Just copy the AUTO'MAPPED'VARS MAP statements from the LSX file back to the original source and then you can compile with /M. That won't help resolve issues related to typos you've already introduced—although perhaps in seeing the AUTO'MAPPED'VARS all together, you might spot some suspicious ones—but it will allow you to benefit going forward.

 

Unreferenced Variables

When the /LF switch is used to create an LSX list file, unreferenced variables are listed at the end, as a convenience for those interested in clearing dead weight out of program. Note, however, that these are not errors, and in many cases, it isn't even desirable to remove them. For example, it is common to group misc variables under a heading, e.g.

MAP1 WORK'VARS

MAP2 X,F

etc.

 

Typically in the above case, there would probably be no explicit reference to WORK'VARS, but you couldn't just delete it without elevating the MAP2 variables beneath it to MAP1. So the new feature is only to be used a guide or ignored as you see fit.

Note: see Compiler Edit History, edits 452 and 500, for additional info on the List File option.

 

Procedure Reference Count

When compiling with /P or /PX, a section will be added to the bottom of the LSX file listing all the procedures and functions defined in the program, along with the reference count—i.e., the number of times the routine is called. For example:

Procedures, Functions [reference count]

======================================================

Fn'NextCh(ch) [2] 

Fn'XMList'Load'Doc($xml,xmldoc$) [1] 

Fn'XMList'Save'Doc($xml,xmldoc$,level,och) [0] 

Fn'XMList'Get'Subtree'Callback($xml,item$,parent$,flags,$response) [1] 

 

In the above example, we can see that there are several functions which are defined but are never used. These don't hurt anything, other than making the RUN modules larger than they need to be, so we might want to remove them. Fortunately, the /PX switch will do this for us automatically, showing a "<nc>" (for Never Called) next to any function that gets removed by this "tree-shaking" feature, e.g.

Procedures, Functions [reference count]

======================================================

Fn'NextCh(ch) [2] 

Fn'Load'Doc($xml,xmldoc$) [1] 

Fn'Save'Doc($xml,xmldoc$,level,och) [0] <nc>

Fn'Get'Subtree'Callback($xml,item$,parent$,flags,$response) [1] <nc>

Fn'Walk($xml,@fn'callback=.NULL,level=0 ,parent$=.null ) [0] <nc>

 

The above shows that the last three functions were removed from the RUN module, because they were never called. Note that this can occur even when the reference count is non-zero, as in the Fn'Get'Subtree'Callback example above, which was apparently referenced once, but still marked <nc>. This occurs when the only references to the target routine occur within other routines which themselves are never called. In the above case, it may be that the function Fn'Walk() references Fn'Get'Subtree'Callback(), but since Fn'Walk() is itself not referenced anywhere and thus never called, then by extension, Fn'Get'Subtree'Callback() is never called, and can thus be removed.

Note that routines that are removed by the /PX switch still show up in the LSX file, but the location counter will not increment. The routines removed this way are essentially treated by the compiler as if removed by conditional compilation logic.

 

See Also

The compiler /LSM switch which generates another kind of list file containing program metadata which is mostly used by APN, but which is somewhat related to the metadata contained in the LSX file.

History

2024 April, A-Shell 7.0.1757, edit 1046:  Add some performance statistics to the end of the LSX file.

2022 February, A-Shell 6.5.1711, edit 967:  LSX file ++include indicators now show a <##_#> suffix indicating the sequential file number and the nesting level.

2019 February, A-Shell 6.5.1656, edit 893:  Expand LSX header.

2016 June, A-Shell 6.3.1514, edit 762:  /PX switch added to the compiler.

2014 March, A-Shell 6.1.1382, edit 663:  Function list with reference count added to LSX

2014 January, A-Shell 6.1.1373, edit 652:  /P switch added to compiler

2007 June, A-Shell 5.0.990, edit 356:  /LF switch added to the compiler (LSX file introduced)

Note that the above feature introductions were subject to various subsequent fixes and enhancements; for details see the Compiler Edit History and search for "LSX."