{ This program produces six 16-bit check digits from a a Pascal program. These check digits can be used to ensure that the Pascal source text has not been changed. The check digits are calculated by using the ISO/CCITT cyclic check approved for data transmission and usually performed by hardware (some 500 times faster than this program). For a description of the checking algorithm, see D W Davies et al. 'Networks and their Protocols' pp263-270. Mark 2 version using sets. V4.2 version has modified error reporting ( see second comment in procedure 'readline'). } program v4p3checktext(input, output); const linelength = 72; { Implementation defined values, to be set for each machine} mincharvalue = 0; maxcharvalue = 255; type lineindex = 1 .. linelength; regindex = 0 .. 16; bits = (one, two, three, four, five, six); setbits = set of bits; ShiftRegister = array [regindex] of setbits; var lpos, lineno, errorlines: integer; firstline, blankline: boolean; line: array [lineindex] of char; SR: ShiftRegister; Convert: array [char] of setbits; procedure pulse( b: setbits); { This algorithm follows Recommendation V41, see 'Data Transmission Over Telephone Network: Series V Recommendations', International Telecommunication Union. Geneva (1977). } var i: regindex; e: setbits; begin for i := 15 downto 0 do SR[i+1] := SR[i]; e := SR[16]; SR[0] := (b + e) - (b * e); SR[5] := (SR[5] + e) - (SR[5] * e); SR[12] := (SR[12] + e) - (SR[12] * e); end; {pulse} procedure initialise; var i: regindex; ch: char; begin for i := 0 to 16 do SR[i] := [ ]; for ch := chr(mincharvalue) to chr(maxcharvalue) do Convert[ch] := [ ]; Convert['a'] := [one]; Convert['A'] := [one]; Convert['b'] := [two]; Convert['B'] := [two]; Convert['c'] := [one,two]; Convert['C'] := [one,two]; Convert['d'] := [one,two,three,four,five,six]; Convert['D'] := [one,two,three,four,five,six]; Convert['e'] := [one,three]; Convert['E'] := [one,three]; Convert['f'] := [two,three]; Convert['F'] := [two,three]; Convert['g'] := [one,two,three]; Convert['G'] := [one,two,three]; Convert['h'] := [four]; Convert['H'] := [four]; Convert['i'] := [one,four]; Convert['I'] := [one,four]; Convert['j'] := [two,four]; Convert['J'] := [two,four]; Convert['k'] := [one,two,four]; Convert['K'] := [one,two,four]; Convert['l'] := [three,four]; Convert['L'] := [three,four]; Convert['m'] := [one,three,four]; Convert['M'] := [one,three,four]; Convert['n'] := [two,three,four]; Convert['N'] := [two,three,four]; Convert['o'] := [one,two,three,four]; Convert['O'] := [one,two,three,four]; Convert['p'] := [five]; Convert['P'] := [five]; Convert['q'] := [one,five]; Convert['Q'] := [one,five]; Convert['r'] := [two,five]; Convert['R'] := [two,five]; Convert['s'] := [one,two,five]; Convert['S'] := [one,two,five]; Convert['t'] := [three,five]; Convert['T'] := [three,five]; Convert['u'] := [one,three,five]; Convert['U'] := [one,three,five]; Convert['v'] := [two,three,five]; Convert['V'] := [two,three,five]; Convert['w'] := [one,two,three,five]; Convert['W'] := [one,two,three,five]; Convert['x'] := [four,five]; Convert['X'] := [four,five]; Convert['y'] := [one,four,five]; Convert['Y'] := [one,four,five]; Convert['z'] := [two,four,five]; Convert['Z'] := [two,four,five]; Convert['0'] := [one,two,four,five]; Convert['1'] := [three,four,five]; Convert['2'] := [one,three,four,five]; Convert['3'] := [two,three,four,five]; Convert['4'] := [one,two,three,four,five]; Convert['5'] := [six]; Convert['6'] := [one,six]; Convert['7'] := [two,six]; Convert['8'] := [one,two,six]; Convert['9'] := [three,six]; Convert['('] := [one,three,six]; Convert[')'] := [two,three,six]; Convert['<'] := [one,two,three,six]; Convert['>'] := [four,six]; Convert['+'] := [one,four,six]; Convert['-'] := [two,four,six]; Convert['*'] := [one,two,four,six]; Convert['/'] := [three,four,six]; Convert['='] := [one,three,four,six]; Convert['.'] := [two,three,four,six]; Convert[','] := [one,two,three,four,six]; Convert[':'] := [five,six]; Convert[';'] := [one,five,six]; Convert['^'] := [two,five,six]; Convert['@'] := [two,five,six]; Convert[' '] := [one,two,five,six]; Convert[''''] := [one,two,three,five,six]; firstline := true; lineno := 0; errorlines := 0; end; {initialise} procedure printx; procedure printreginhex( b: bits); const fourzeros = '0000'; type bitstring = packed array[1..4] of char; var i: regindex; subreg1,subreg2,subreg3,subreg4 : bitstring; procedure prnt(subreg : bitstring); const hex0='0000'; hex1='0001'; hex2='0010'; hex3='0011'; hex4='0100'; hex5='0101'; hex6='0110'; hex7='0111'; hex8='1000'; hex9='1001'; hexA='1010'; hexB='1011'; hexC='1100'; hexD='1101'; hexE='1110'; hexF='1111'; begin if subreg=hex0 then write('0') else if subreg=hex1 then write('1') else if subreg=hex2 then write('2') else if subreg=hex3 then write('3') else if subreg=hex4 then write('4') else if subreg=hex5 then write('5') else if subreg=hex6 then write('6') else if subreg=hex7 then write('7') else if subreg=hex8 then write('8') else if subreg=hex9 then write('9') else if subreg=hexA then write('A') else if subreg=hexB then write('B') else if subreg=hexC then write('C') else if subreg=hexD then write('D') else if subreg=hexE then write('E') else if subreg=hexF then write('F') end; {prnt} begin subreg1 := fourzeros; subreg2 := fourzeros; subreg3 := fourzeros; subreg4 := fourzeros; for i := 0 to 3 do if b in SR[i] then subreg1[i+1] := '1'; for i := 4 to 7 do if b in SR[i] then subreg2[i-3] := '1'; for i := 8 to 11 do if b in SR[i] then subreg3[i-7] := '1'; for i := 12 to 15 do if b in SR[i] then subreg4[i-11] := '1'; prnt(subreg1); prnt(subreg2); prnt(subreg3); prnt(subreg4); write( ' ' ); end; {printreginhex} begin writeln( 'Check digits are' ); printreginhex(one); printreginhex(two); printreginhex(three); printreginhex(four); printreginhex(five); printreginhex(six); writeln; writeln( 'Total number of lines', lineno : 8); if errorlines > 0 then writeln( 'Total number of errors', errorlines : 7); writeln end; {printx} procedure readline; { Ignores initial spaces, Replaces brackets by longer alternatives, Checks characters after 'linelength' are spaces, Set 'lpos' to ignore trailing spaces, Set 'blankline' as necessary.} { In V4.2, error messages are output only for the first overlength line or the first line with non-spaces after column 72, plus any lines in the first ten errors containing non Pascal characters (to keep the CHECKTEXT output consistent with that given in earlier releases). The total number of lines with errors is given. These changes have been made to allow the CHECKTEXT program to be used for checking the output produced during validation runs. } var ch: char; charsread: integer; procedure sub(chx, ch1, ch2: char); { Substitute ch1 and ch2 for chx } begin if ch = chx then begin if lpos > 72 then begin if errorlines = 0 then writeln(' Line too long, line no', lineno); errorlines := errorlines + 1 end else begin line[lpos-1] := ch1; line[lpos] := ch2; end; lpos := lpos + 1; charsread := charsread + 1 end; end; { sub } begin lineno := lineno + 1; if eoln(input) then blankline := true else begin ch := input^; charsread := 0; while (ch = ' ') and (not eoln(input)) do begin get(input); charsread := charsread + 1; ch := input^; end; if eoln(input) then blankline := true else begin blankline := false; lpos := 1; while not eoln(input) do begin if lpos <= 72 then line[lpos] := ch; lpos := lpos + 1; { Text to be deleted if curly brackets not supported} sub( '{', '(', '*' ); sub( '}', '*', ')' ); { End of curly bracket text } { Text to be deleted if square brackets not supported} sub( '[', '(', '.' ); sub( ']', '.', ')' ); { End of square bracket text } if (charsread > 72) and (ch <> ' ') then begin if errorlines = 0 then writeln( 'Non-spaces after col 72 on line', lineno ); errorlines := errorlines + 1 end; get(input); charsread := charsread + 1; ch := input^; end; lpos := lpos - 1; if lpos > 72 then lpos := 72; while line[lpos] = ' ' do lpos := lpos - 1; end; end; get(input); end; {readline} procedure processline; { Checks all characters are valid Pascal characters. Call check for each character. } var i: lineindex; j: setbits; begin for i := 1 to lpos do begin if firstline then write(line[i]); j := Convert[line[i]]; if j = [ ] then begin if errorlines < 10 then writeln( 'Non Pascal Character =', line[i], 'on line no', lineno); errorlines := errorlines +1 end else pulse(j); end; if firstline then writeln; pulse([one,three,five,six]); firstline := false; end; {processline} begin initialise; while not eof(input) do begin readline; if not blankline then processline; end; printx; end.