When reading an RFC published by the IETF, it's hard to know what content has been corrected without explicitly checking the errata. For example, in RFC 7049 Section 2.4.2, the following correction exists in the errata:
diff --git a/rfc7049.txt b/rfc7049.txt
index 5d29907..c7c20e6 100644
--- a/rfc7049.txt
+++ b/rfc7049.txt
## -886,7 +886,7 ## RFC 7049 CBOR October 2013
and eight bytes 0x00). In hexadecimal:
C2 -- Tag 2
- 29 -- Byte string of length 9
+ 49 -- Byte string of length 9
010000000000000000 -- Bytes content
But to realize this particular section was corrected, I'd have to go through the errata beforehand and write down all the sections that have corrections. Then, if I come across a section that was corrected, I'd have to look back at the errata and find what that particular correction was.
So, to simplify this process, does the IETF publish versions RFCs that include errata?
From what I understand, a standards track IETF RFC is a reference, and therefore, should not change. This is why errata are published separately. However, the IETF does indeed provide RFCs with the errata included with the following caveat:
This is a purely informative rendering of an RFC that includes verified errata. This rendering may not be used as a reference.
For this particular RFC, one may find the version with errata included at the following location:
https://www.rfc-editor.org/rfc/beta/errata/RFC7049.html, which was navigated to from https://datatracker.ietf.org/doc/rfc7049/ by clicking the with errata button in the Document > Formats section.
Related
Creating swapchain images with wrong format result this obviously:
vkCreateImageView() format VK_FORMAT_B8G8R8A8_UNORM differs from VkImage
0x40000000004[] format VK_FORMAT_B8G8R8A8_SRGB. Formats MUST be IDENTICAL unless
VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.
VK_KHR_swapchain_mutable_format Requires Vulkan 1.0
it result this:
The Vulkan spec states: If flags contains VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR
then the pNext chain must include a VkImageFormatListCreateInfo structure with a viewFormatCount
greater than zero and pViewFormats must have an element equal to imageFormat
VkImageFormatListCreateInfo Provided by VK_VERSION_1_2
Question - how Vulkan 1.0 extension require 1.2 structure? (maybe I'm missing something idk)
And as I see on https://vulkan.gpuinfo.org/listextensions.php VK_KHR_swapchain_mutable_format supported only by 60% of Vulkan GPUs... so better write "hand conversion"?
VkImageFormatListCreateInfo Provided by VK_VERSION_1_2
You linked to the Vulkan 1.2 specification. So of course it cites itself. The extension in question is a core part of 1.2, as is VkImageFormatListCreateInfo.
The actual extension cites another extension:
Requires VK_KHR_image_format_list
Which defines the VkImageFormatListCreateInfoKHR structure used by the swapchain format extension. This structure is of course equivalent to the core 1.2 structure VkImageFormatListCreateInfo, since "image_format_list" was promoted to core in Vulkan 1.2.
I'm looking at the stratum protocol and I'm having a problem with the nbits value of the mining.notify method. I have trouble calculating it, I assume it's the currency difficulty.
I pull a notify from a dogecoin pool and it returned 1b3cc366 and at the time the difficulty was 1078.52975077.
I'm assuming here that 1b3cc366 should give me 1078.52975077 when converted. But I can't seem to do the conversion right.
I've looked here, here and also tried the .NET function BitConverter.Int64BitsToDouble.
Can someone help me understand what the nbits value signify?
You are right, nbits is current network difficulty.
Difficulty encoding is throughly described here.
Hexadecimal representation like 0x1b3cc366 consists of two parts:
0x1b -- number of bytes in a target
0x3cc366 -- target prefix
This means that valid hash should be less than 0x3cc366000000000000000000000000000000000000000000000000 (it is exactly 0x1b = 27 bytes long).
Floating point representation of difficulty shows how much current target is harder than the one used in the genesis block.
Satoshi decided to use 0x1d00ffff as a difficulty for the genesis block, so the target was
0x00ffff0000000000000000000000000000000000000000000000000000.
And 1078.52975077 is how much current target is greater than the initial one:
$ echo 'ibase=16;FFFF0000000000000000000000000000000000000000000000000000 / 3CC366000000000000000000000000000000000000000000000000' | bc -l
1078.52975077482646448605
While parsing the NMEA output of a GPS receiver I get the following lines:
$GPGSV,4,1,16,02,17,228,35,03,04,048,37,05,59,285,29,06,02,030,34*73
$GPGSV,4,2,16,07,58,061,46,08,80,159,40,09,11,227,32,10,51,167,47*77
$GPGSV,4,3,16,13,15,089,38,15,00,279,,16,00,018,,26,34,279,42*7A
$GPGSV,4,4,16,28,20,154,39*4C
As I understand it, from various sources on the web (e.g. here), this is wrong. According to the 3rd number, there should be 16 satellites, which was true for all those GPS receivers I previously encountered, but the sentence from this one only contains the data for 13 satellites.
Is this an error? Or do I read the specification wrongly?
Nmea is a weakly specified file format. GPS chip manufactures provide documenttaion how they interpret the NMEA specification.
For example ublox and Sirf each have a chapter of about 40 pages describing how to interpret the NMEA format.
So if you write " Or do I read the specification wrongly?", then the question is which specification you are reading. That of the GPS chip manufacturer? The NMEA 0183 spec does not contain enough info to correctly parse the sentences.
Especially in your case: the NMEA protocol does not desribe how to handle empty values vs invalid ones.
In your case the receiver theretically expects to see 16 satellites, but found only 13.
I would expect that the missing 3 sats would have empty ",,,,,,,,". But obviously the manufacturer decided to just stop and append the checksum string. (Its simply not speciefied that it is mandatory to print out empty semicolons for the missing 3 sats.
Unfortunaetly you have to expect to write a NMEA parser for each CHPS chip manufacturer.
Therfore I always recommend to use the binary format of the Chip manufactureres protocol. (e,.g uBlox bianry or Sirf binary because these are exactly specified).
You can further look at the docu for GpsBable: they show how different manufacturres produce different GSV data sets.
Update:
As you now told that it is a ublox receiver:
The answer is, yes the NMEA sentences are valid. Look at the ublox protocol spec. i use spec for ublox 5:
On page where the GSV sentence is described look at the "Message Structure":
{,sv,elv,az,cno}*cs
the curly braces enclose the sequence that is repeated.
And below look at "1..4": this means 1,2,3 or 4 blocks. There is not written "4", its "1..4" therefore satelite info is optional, and has not to be empty.
If you further look at the example ublox gives, then you see, that the last GPGSV message contains less than 4 satellites, exactly as you are showing in your question.
Yes, it's inconsistent; the last message should have described more than one satellite (four, actually) so as to total the 16 advertised. The GPS receiver should have reported at least the satellite IDs (PRN), even if their viewing direction in the sky and SNR were unknown at the time, e.g.: {,01,,,}.
That being said, it's better to write programs tolerant against ill-formed messages; in this case, updating the number of satellites in view to 13, as counted.
(I've checked the checksums and they're okay.)
I've been doing some preliminary research in the area of message digests. Specifically collision attacks of cryptographic hash functions such as MD5 and SHA-1, such as the Postscript example and X.509 certificate duplicate.
From what I can tell in the case of the postscript attack, specific data was generated and embedded within the header of the postscript file (which is ignored during rendering) which brought about the internal state of the md5 to a state such that the modified wording of the document would lead to a final MD value equivalent to the original postscript file.
The X.509 took a similar approach where by data was injected within the comment/whitespace sections of the certificate.
Ok so here is my question, and I can't seem to find anyone asking this question:
Why isn't the length of ONLY the data being consumed added as a final block to the MD calculation?
In the case of X.509 - Why is the whitespace and comments being taken into account as part of the MD?
Wouldn't a simple processes such as one of the following be enough to resolve the proposed collision attacks:
MD(M + |M|) = xyz
MD(M + |M| + |M| * magicseed_0 +...+ |M| * magicseed_n) = xyz
where :
M : is the message
|M| : size of the message
MD : is the message digest function (eg: md5, sha, whirlpool etc)
xyz : is the pairing of the acutal message digest value for the message M and |M|. <M,|M|>
magicseed_{i}: Is a set of random values generated with seed based on the internal-state prior to the size being added.
This technqiue should work, as to date all such collision attacks rely on adding more data to the original message.
In short, the level of difficulty involved in generating a collision message such that:
It not only generates the same MD
But is also comprehensible/parsible/compliant
and is also the same size as the original message,
is immensely difficult if not near impossible. Has this approach ever been discussed? Any links to papers etc would be nice.
Further Question: What is the lower bound for collisions of messages of common length for a hash function H chosen randomly from U, where U is the set of universal hash functions ?
Is it 1/N (where N is 2^(|M|)) or is it greater? If it is greater, that implies there is more than 1 message of length N that will map to the same MD value for a given H.
If that is the case, how practical is it to find these other messages? bruteforce would be of O(2^N), is there a method of time complexity less than bruteforce?
Can't speak for the rest of the questions, but the first one is fairly simple - adding length data to the input of the md5, at any stage of the hashing process (1st block, Nth block, final block) just changes the output hash. You couldn't retrieve that length from the output hash string afterwards. It's also not inconceivable that a collision couldn't be produced from another string with the exact same length in the first place, so saying "the original string was 17 bytes" is meaningless, because the colliding string could also be 17 bytes.
e.g.
md5("abce(17bytes)fghi") = md5("abdefghi<long sequence of text to produce collision>")
is still possible.
In the case of X.509 certificates specifically, the "comments" are not comments in the programming language sense: they are simply additional attributes with an OID that indicates they are to be interpreted as comments. The signature on a certificate is defined to be over the DER representation of the entire tbsCertificate ('to be signed' certificate) structure which includes all the additional attributes.
Hash function design is pretty deep theory, though, and might be better served on the Theoretical CS Stack Exchange.
As #Marc points out, though, as long as more bits can be modified than the output of the hash function contains, then by the pigeonhole principle a collision must exist for some pair of inputs. Because cryptographic hash functions are in general designed to behave pseudo-randomly over their inputs, collisions will tend toward being uniformly distributed over possible inputs.
EDIT: Incorporating the message length into the final block of the hash function would be equivalent to appending the length of everything that has gone before to the input message, so there's no real need to modify the hash function to do this itself; rather, specify it as part of the usage in a given context. I can see where this would make some types of collision attacks harder to pull off, since if you change the message length there's a changed field "downstream" of the area modified by the attack. However, this wouldn't necessarily impede the X.509 intermediate CA forgery attack since the length of the tbsCertificate is not modified.
Why does COBOL have both SECTION and PARAGRAPH?
Can anybody explain why the designers of COBOL created both SECTIONs and PARAGRAPHs? These have been around since the initial release of COBOL so I suspect the real reason for their existence has long since gone away (similar to things like NEXT SENTENCE which are still in the language specification for backward compatibility but no longer required since the introduction of explicit scope terminators).
My guess is that SECTION may have been introduced to support program overlays. SECTION has an optional PRIORITY number associated with it to identify the program overlay it is part of. However, most modern implementations of COBOL ignore or have dropped PRIORITY numbers (and overlays).
Currently, I see that SECTIONs are still required in the DECLARATIVE part of the PROCEDURE DIVISION, but can find no justification for this. I see no semantic difference between SECTION and PARAGRAPH other than PARAGRAPH is subordinate to SECTION.
Some COBOL shops ban the use of SECTION in favour of PARAGRAPH (seems common in North America). Others ban PARAGRAPH in favour of SECTION (seems common in Europe). Still others have guidelines as to when each is appropriate. All of this seems highly arbitrary to me - which begs the question: Why were they put into the language specification in the first place? And, do they have any relevance today?
If you answer this question, it would be great if you could also point to a reference to support your answer.
Thanks
No references on this, since I heard it passed on to me from one of the old timers in my shop but...
In the old COBOL compilers, at least for IBM and Unisys, sections were able to be loaded into memory one at a time. Back in the good old days when memory was scarce, a program that was too large to be loaded into memory all at once was able to be modularized for memory usage using sections. Having both sections and paragraphs allowed the programmer to decide which code parts were loaded into memory together if they couldn't all be loaded at once - you'd want two parts of the same perform loop loaded together for efficiency's sake. Nowadays it's more or less moot.
My shop uses paragraphs only, prohibits GOTO and requires exit paragraphs, so all our PERFORMS are PERFORM 100-PARAGRAPH THRU 100-EXIT or something similar - which seems to make the paragraphs more like sections to me. But I don't think that there's really much of a difference now.
I learned COBOL around 1978, on an ICL 2903. I have a vague memory that the SECTION headers could be assigned a number range, which meant that those SECTION headers could be swapped in and out of memory, when the program was too large for memory.
I know this is an old question, but the OP requested about documentation on the original justification of the use of SECTION as well as PARAGRAPH in COBOL.
You can't get much more "original" than the CODASYL Journal documentation.
in section 8 of the Journal's specification for the language,
"COBOL segmentation is a facility that provides a means by which the
user may communicate with the compiler to specify object program
overlay requirements"
( page 331, section 8.1 "Segmentation - General Description")
"Although it is not mandatory, the Procedure Division for a source
program is usually written as a consecutive group of sections, each of
which is composed of a series of closely related operations that are
designed to collectively perform a particular function. However s when
segmentation is used, the entire Procedure Division must be in
sections. In addition, each section must be classified as belonging
either to the fixed portion or to one of the independent segments of
the object program. Segmentation in no way affects the need for
qualification of procedure-names to insure uniqueness."
(p 331, section 8.1.2.1 "Program Segments")
In her book on comparative programming languages ("Programming Languages: History and Fundamentals", 1969) Jean Sammet (who sat on the CODASYL committee, representing Sylvania Electric) states:
".. The storage allocation is handled automatically by the compiler.
The prime unit for allocating executable code is a group of sections
called a segment. The programmer combines sections be specifying a
priority number with each section's name. ... The compiler is required
to see that the proper control transfers are provided so that control
among segments which are not stored simultaneously can take place.
..."
(p 369 - 371 V.3 COBOL)
Well, the simplest of the reasons is that SECTION s provide you the "modularity" -- just as functions in C -- a necessity in the "structured" programs. You would notice that code written using SECTIONs appears far more readable than the code written just in paragraphs, for every section has to have an "EXIT" -- a sole and very explicit exit point from a SECTION (exit point of a paragrpah is far more vague and implicit, i.e. until a new paragraph declaration is found). Consider this example and you may be tempted to use sections in your code:
*==================
MAINLINE SECTION.
*==================
PERFORM SEC-A
PERFORM SEC-B
PERFORM SEC-C
GOBACK.
*==================
MAINLINE-EXIT.
*==================
EXIT.
*==================
SEC-A SECTION.
*==================
.....
.....
.....
.....
IF <cond>
go to A-EXIT
end-if
.....
.....
.....
.....
.
*==================
A-EXIT.
*==================
EXIT.
Don't think you would have this sort of a privlege when writing your codes in paragraphs. You may have had to write a huge ELSE statement to cover up the statements you didn't want to execute when a certain condition is reached (consider that set of statements to be running across 2-3 pages... a further set of IF / ELSE would cramp you up for indentation). Of course, you'll have to use "GO TO" to achieve this, but you can always direct your professionals not to use GO TOs except while Exiting, which is a fair deal, I think.
So, whilst I also agree that anything that can be written using SECTIONs can also be written using paragraphs (with little or no tweaks), my personal choice would be to go for an implementation that can make the job of my developers a little easier in future!
Cobol was developed in the mid-50's. As the full name alludes, it was developed for business programming, as being a language more relevant for business purposes than the existing "scientific" or "technical" languages (there were very few "languages" anyway, and "machine code" (specific, of course, to a particular architechture (I nearly said "specific chip", before thinking of vacuum tubes)) which may have to be set through physical switches/dials on some machines) and if lucky with an "Assembler". Cobol was very advanced for its day, for its purpose.
The intention was for programs written in Cobol to be much more like English-language than just a set of "codes" which mean something to the initiated.
If you look at some of the nomenclature relating to the language - paragraph, sentence, verb, clause - it is deliberately following the patterns ascribed to the English language.
SECTION doesn't quite fit into this, until you relate things to a formal business document.
Both SECTIONs and paragraphs also appear outside the PROCEDURE DIVISION. As in written English, paragraphs can exist on their own, or can be a part of a SECTION.
SECTIONs may have a priority-number which relates to the "segmentation feature". This used to include "overlaying" of SECTIONs to afford a primitive level of memory management. This is a "computing featuer" rather than an English-language one :-) The "segmentation feature" does have something of a remaining affect, but I've never seen it actually used.
Without DECLARATIVES (which I don't use, and have just noticed the manual to be unclear upon) then it is "choice" as to whether SECTIONs or paragraphs are used for PERFORM.
If GO TO is used, rationally, "equivalence" can be achieved with PERFORM ... TRHU .... If not, and there is not gratuitous use of PERFORM ... THRU ..., then there is equivalence already.
Comparisons to "structured" code and modern languages are "reading history backwards" or just outlining a particular "practice". From the reputation attained by "spaghetti code" and ALTER ... TO PROCEED TO ... it may well be that for 20 years it was "common" to not do much with PERFORM unless you needed the "memory management", but I have no references or knowledge to back this up.
SECTIONs allow duplicate paragraph-names, otherwise paragraph-names must be unique.
I can't put a specific finger on one over the other all the time.
If using GO TO, I'd use SECTIONs. If not, paragraphs. With DECLARATIVES I'd use SECTIONs. If using SECTIONs I'd start PROCEDURE DIVISION with a SECTION to avoid a diagnostic message.
Local standards may dictate, but not necessarily on a "modern" (or even "rational") basis. Much is "known" but actually misunderstood about SECTIONs and paragraphs, in my experience.
For performance (where masses of data is being processed, and I mean masses) then a PERFORM of one SECTION rather than multiple individual paragraphs would see improvements. The effect would be the same with PERFORM ... THRU ..., but I prefer not to recommend it.
GO TO outside the range of a PERFORM is 1) bad 2) can lose out on "optimization". Shouldn't be a problem *except" when GO TO abend/exception and not expecting any logical return. If the use of this is felt to be necessarily "immediately", then it is better done with a PERFORM despite the "counter-intuitive" aspect (so document it).
For one thing, paragraph names must be unique unless they are in separate sections, so sections allow for "namespacing" of paragraphs.
If I recall correctly, the only reason you must use a SECTION is for DECLARATIVES. Aside from that they are optional and primarily useful for grouping paragraphs. I think it's common (relatively speaking, anyway) to require that PERFORM be used on paragraphs only when they are in the same section.
A section can have several paragraphs in it. When you PERFORM a section, it executes all the paragraphs in the section. Within the section you can use PERFORM or GOTO to branch to the paragraphs within the section.
I will do the best I can to answer this. If your only coding exposure is x86 or ARM then you will have significant difficulty. Yes those chips sell a lot but that doesn't mean they are good, just cheap enough people don't mind throwing them away.
Much of this information can be found in "The Minimum You Need to Know to Be an OpenVMS Application Developer." You will find it is one of the scant few titles on Dr. Dobb's recommended reading list for all developers. Yes, I wrote it. It is also the book recommended by HP OpenVMS Engineering group for developers looking to learn the platform.
My COBOL on that platform mostly happened during the 1980s when it was VAX/VMS. Then it became OpenVMS; Alpha/OpenVMS; Itanium/OpenVMS; and soon to be x86/OpenVMS. On a real computer with a real operating system, sections have meaning. Every section created a PSECT. In linker terms that was short for Program SECtion. Based on what the section was, various load attributes were set. Each PSECT would be loaded into one or more 512 Byte memory pages. Memory pages were designed to be the exact same size as a disk block. VMS stood for Virtual Memory System. IBM had several of their own operating systems which, under the hood were different, but they too were true virtual memory systems. This wasn't "overlay linking." That's an x86 term and came about due to severe architectural flaws.Read up on Compact, Small, Medium, and Large "memory models" from the 286 days on forward. Also read up on EMS and XMS memory paging. Oiy was THAT fun!
Here is one of the numerous programs found in that book.
IDENTIFICATION DIVISION.
PROGRAM-ID. COB_ZILL_DUE_REPORT_SUB.
AUTHOR. Roland Hughes.
DATE-WRITTEN. 2005-02-08.
DATE-COMPILED. TODAY.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT DRAW-STATS
ASSIGN TO 'DRAWING_STATS'
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS ELM_NO IN DSTATS-REC
LOCK MODE IS AUTOMATIC
FILE STATUS IS D-STAT.
SELECT MEGA-STATS
ASSIGN TO 'MEGA_STATS'
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS ELM_NO IN MSTATS-REC
LOCK MODE IS AUTOMATIC
FILE STATUS IS M-STAT.
SELECT SORT-FILE ASSIGN TO 'TMP.SRT'.
SELECT SORTED-FILE ASSIGN TO DISK.
SELECT RPT-FILE ASSIGN TO 'ZILL_DUE.RPT'.
DATA DIVISION.
FILE SECTION.
FD DRAW-STATS
IS GLOBAL
LABEL RECORDS ARE STANDARD.
COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
REPLACING ZILLIONARE_STATS_RECORD BY DSTATS-REC.
FD MEGA-STATS
IS GLOBAL
LABEL RECORDS ARE STANDARD.
COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
REPLACING ZILLIONARE_STATS_RECORD BY MSTATS-REC.
FD RPT-FILE
LABEL RECORDS ARE OMITTED.
01 RPT-DTL PIC X(80).
SD SORT-FILE.
COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
REPLACING ZILLIONARE_STATS_RECORD BY SORT-REC.
FD SORTED-FILE
VALUE OF ID IS SORTED-FILE-NAME.
COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
REPLACING ZILLIONARE_STATS_RECORD BY SORTED-REC.
Data declarations
WORKING-STORAGE SECTION.
01 CONSTANTS.
05 SORT-FILE-NAME PIC X(7) VALUE 'TMP.SRT'.
05 SORTED-FILE-NAME PIC X(8) VALUE 'STAT.SRT'.
01 STATUS-VARIABLES.
05 M-STAT PIC X(2).
05 D-STAT PIC X(2).
05 EOF-FLAG PIC X.
88 IT-IS-END-OF-FILE VALUE 'Y'.
01 STUFF.
05 TODAYS-DATE.
10 TODAY_YYYY PIC X(4).
10 TODAY_MM PIC X(2).
10 TODAY_DD PIC X(2).
05 TODAYS-DATE-FORMATTED.
10 FMT_MM PIC Z9.
10 FILLER PIC X VALUE '/'.
10 FMT_DD PIC 99.
10 FILLER PIC X VALUE '/'.
10 FMT_YYYY PIC 9(4).
05 FLT-1 COMP-2.
05 WORK-STR PIC X(65).
01 REPORT-DETAIL.
05 ELM-NO-DTL PIC Z9.
05 FILLER PIC X(3).
05 HIT-COUNT-DTL PIC ZZZ9.
05 FILLER PIC X(3).
05 SINCE-LAST-DTL PIC ZZZ9.
05 FILLER PIC X(5).
05 PCT-HITS-DTL PIC Z9.999.
05 FILLER PIC X(4).
05 AVE-BTWN-DTL PIC ZZ9.999.
01 REPORT-HDR1.
05 THE-DATE PIC X(12).
05 FILLER PIC X(20).
05 PAGE-TITLE PIC X(17).
01 REPORT-HDR2.
05 FILLER PIC X(33).
05 GROUP-TITLE PIC X(20).
01 REPORT-HDR3.
05 HDR3-TXT PIC X(40) VALUE
'No Hits Since Pct_hits Ave_btwn'.
01 REPORT-HDR4.
05 HDR4-TXT PIC X(40) VALUE
'-- ---- ----- -------- --------'.
PROCEDURE DIVISION.
A000-MAIN.
PERFORM B000-HSK.
SORT SORT-FILE
ON DESCENDING KEY SINCE_LAST IN SORT-REC
INPUT PROCEDURE IS S000-DSTAT-INPUT
GIVING SORTED-FILE.
PERFORM B010-REPORT-DRAWING-NUMBERS.
STRING SORT-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
STRING SORTED-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
*
* Set up for second part of report
*
MOVE SPACES TO RPT-DTL.
WRITE RPT-DTL BEFORE ADVANCING PAGE.
MOVE SPACES TO EOF-FLAG.
MOVE ' Mega Drawing Numbers' TO GROUP-TITLE.
SORT SORT-FILE
ON DESCENDING KEY SINCE_LAST IN SORT-REC
INPUT PROCEDURE IS S001-MSTAT-INPUT
GIVING SORTED-FILE.
PERFORM B010-REPORT-DRAWING-NUMBERS.
STRING SORT-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
STRING SORTED-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
CLOSE RPT-FILE.
CALL 'LIB$SPAWN' USING BY DESCRIPTOR 'EDIT/READ ZILL_DUE.RPT'.
EXIT PROGRAM.
Paragraph to initialize our data and files.
B000-HSK.
CALL 'COB_FILL_IN_LOGICALS'.
MOVE SPACES TO STATUS-VARIABLES.
ACCEPT TODAYS-DATE FROM DATE YYYYMMDD.
MOVE TODAY_YYYY TO FMT_YYYY.
MOVE TODAY_DD TO FMT_DD.
MOVE TODAY_MM TO FMT_MM.
OPEN OUTPUT RPT-FILE.
MOVE SPACES TO REPORT-HDR1.
MOVE TODAYS-DATE-FORMATTED TO THE-DATE.
MOVE 'Due Number Report' to PAGE-TITLE.
MOVE SPACES TO REPORT-HDR2.
MOVE 'Drawing Numbers' TO GROUP-TITLE.
Paragraph to process the sorted selection file and
create the portion of the report relating to drawing
numbers.
B010-REPORT-DRAWING-NUMBERS.
MOVE SPACES TO EOF-FLAG.
OPEN INPUT SORTED-FILE.
READ SORTED-FILE
AT END SET IT-IS-END-OF-FILE TO TRUE.
PERFORM C010-DRAWING-HEADINGS.
PERFORM UNTIL IT-IS-END-OF-FILE
MOVE SPACES TO REPORT-DETAIL
MOVE ELM_NO IN SORTED-REC TO ELM-NO-DTL
MOVE HIT_COUNT IN SORTED-REC TO HIT-COUNT-DTL
MOVE SINCE_LAST IN SORTED-REC TO SINCE-LAST-DTL
MOVE PCT_HITS IN SORTED-REC TO PCT-HITS-DTL
MOVE AVE_BTWN IN SORTED-REC TO AVE-BTWN-DTL
MOVE REPORT-DETAIL TO RPT-DTL
WRITE RPT-DTL BEFORE ADVANCING 1 LINE
READ SORTED-FILE
AT END SET IT-IS-END-OF-FILE TO TRUE
END-READ
END-PERFORM.
CLOSE SORTED-FILE.
Paragraph to print headings for the main drawing numbers
Which are due.
C010-DRAWING-HEADINGS.
MOVE SPACES TO RPT-DTL.
MOVE REPORT-HDR1 TO RPT-DTL.
WRITE RPT-DTL BEFORE ADVANCING 2 LINES.
MOVE SPACES TO RPT-DTL.
MOVE REPORT-HDR2 TO RPT-DTL.
WRITE RPT-DTL BEFORE ADVANCING 1 LINE.
MOVE SPACES TO RPT-DTL.
MOVE REPORT-HDR3 TO RPT-DTL.
WRITE RPT-DTL BEFORE ADVANCING 1 LINE.
MOVE SPACES TO RPT-DTL.
MOVE REPORT-HDR4 TO RPT-DTL.
WRITE RPT-DTL BEFORE ADVANCING 1 LINE.
Paragraph to filter due numbers into sort file.
Creates a floating point temporary to compare against
floating point value from input file. When greater
record is released to the sort file.
S000-DSTAT-INPUT.
OPEN INPUT DRAW-STATS.
READ DRAW-STATS NEXT
AT END SET IT-IS-END-OF-FILE TO TRUE.
PERFORM UNTIL IT-IS-END-OF-FILE
MOVE SINCE_LAST IN DSTATS-REC TO FLT-1
IF FLT-1 >= AVE_BTWN IN DSTATS-REC
MOVE DSTATS-REC TO SORT-REC
RELEASE SORT-REC
END-IF
READ DRAW-STATS
AT END SET IT-IS-END-OF-FILE TO TRUE
END-READ
END-PERFORM.
CLOSE DRAW-STATS.
Paragraph to filter due numbers into sort file.
Creates a floating point temporary to compare against
floating point value from input file. When greater
record is released to the sort file.
S001-MSTAT-INPUT.
OPEN INPUT MEGA-STATS.
READ MEGA-STATS NEXT
AT END SET IT-IS-END-OF-FILE TO TRUE.
PERFORM UNTIL IT-IS-END-OF-FILE
MOVE SINCE_LAST IN MSTATS-REC TO FLT-1
IF FLT-1 >= AVE_BTWN IN MSTATS-REC
MOVE MSTATS-REC TO SORT-REC
RELEASE SORT-REC
END-IF
READ MEGA-STATS
AT END SET IT-IS-END-OF-FILE TO TRUE
END-READ
END-PERFORM.
CLOSE MEGA-STATS.
END PROGRAM COB_ZILL_DUE_REPORT_SUB.
Sorry for the way the "code" feature works in this editor.
Certain sections have to exist. Your program cannot do I-O without an INPUT-OUTPUT SECTION. This is where you map names to physical storage.
If you have an INPUT-OUTPUT SECTION then you have to have a FILE SECTION. This is where you define the record layout(s) of each named file. LABEL RECORDS are always STANDARD when dealing with disk data files and OMITTED when writing report text files. There are a few other clauses I don't remember. Please note the SD included in all of those FD statements. FD is File Definition and SD is Sort Definition.
If you are going to have any local variables you have to have a WORKING-STORAGE SECTION. You cannot declare variables on the fly, they all have to be declared here. This PSECT gets a DATA segment attribute among other things. If you call some service or something and it has a bad address, attempting to execute code within this PSECT the operating system will shoot your application out of the saddle.
All PSECTs created after PROCEDURE DIVISION are flagged EXEC, write protected. If you try to overwrite anything in here during execution the operating system will shoot your program out of the saddle. Any other program attempting to write here will also be shot out of the saddle.
Scan down to the SORT SORT-FILE in A000-MAIN. The COBOL sort routine is amazing. Notice that I provided an INPUT PROCEDURE and it is a paragraph. On IBM mainframes running ROSCOE back in the day this had to be an INPUT SECTION. They needed different attributes on the PSECT so the system sort routine could read/write.
Here is a snippet from another program in that book.
*
* FMS definitions
*
COPY 'COBFDVDEF' OF 'MEGA_TEXT_LIB'.
LINKAGE SECTION.
01 FMS-STUFF.
05 FMSSTATUS PIC S9(9) COMP.
05 RMSSTATUS PIC S9(9) COMP.
05 TCA PIC X(12).
05 WORKSPACE PIC X(12).
PROCEDURE DIVISION USING FMS-STUFF.
The linkage section creates a PSECT of sharable memory. When you call external routines which return values, they need to be here.You must also grant your PROCEDURE DIVISION access to various things it needs in the linkage section.
As you can see from this snippet later in the code
B010-USER-INPUT.
PERFORM C000-FORWARD-LOAD
CALL 'FDV$PUTAL' USING BY DESCRIPTOR SCREEN-REC.
MOVE SPACES TO WORK-STR.
CALL 'FDV$GETAL' USING BY DESCRIPTOR WORK-STR
BY REFERENCE TERMINATOR.
EVALUATE TERMINATOR
WHEN FDV$K_FK_E6 SET LOAD-FORWARD TO TRUE
WHEN FDV$K_FK_E5 SET LOAD-REVERSE TO TRUE
WHEN FDV$K_FK_F10 SET WE-ARE-DONE TO TRUE
END-EVALUATE.
you can pass any local variable you wish as long as you pass it correctly. It's the writing which needs special PSECT attributes.
It's late and I'm tired but I seem to remember you could could have USING clauses on SECTION declarations in the PROCEDURE DIVISION. The on-line documentation available for COBOL, at least that indexed by GOOGLE really is quite worthless. If you want more detailed information search for a circa 1980s COBOL textbook. It won't have any of the new stuff but it will answer many questions.
Here's a kind of bad tutorial on COBOL structure.
We use COBOL SECTION coding in all of our 37K MVS batch COBOL programs. We use this technique to get much faster run times and significantly reduced CPU overhead. This COBOL coding technique is very similar to high performance batch assembler.
Call it High Performance Functionally Structured COBOL programming
Once a SECTION is defined all PERFORM xxxxx will return at the next coded SECTION not the next paragraph in the SECTION. If paragraphs are coded ahead of the first SECTION then they can be executed normally. (But we don't allow this)
Using a SECTION has higher overhead than when using and PERFORM ing only paragraphs - U N L E S S - you use GOTO logic to bypass code that should be conditionally executed. Our rule is that a GOTO can only point to a Tag-Line in the same SECTION. (a paragraph) All paragraphs in a SECTION must be a sub function of the SECTION s function. The EXIT instruction is an assembler NOP instruction. It allow for a Tag-Line to be placed before the next SECTION - a fast exit/return.
Executing a PERFORM xxxx THRU yyyy has more CPU overhead than execution a SECTION without the GOTO s.
WARNING: Executing a PERFORM xxxx Tag-Line in a SECTION will fall thru all the code in the SECTION until the next SECTION is encountered. A GOTO Tag-Line outside of the current SECTION will fall thru all the code in the new landing SECTION until the next SECTION is encountered. (But we don't allow this)