home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol6n02.zip / PARSE.ASM < prev    next >
Assembly Source File  |  1987-12-13  |  16KB  |  299 lines

  1. ;                Parse.asm
  2. ;  Returns character, word and sentence count
  3. ;  count of ASCII files that is compiled into
  4. ;  a reading level index .
  5. ;       Syntax   PARSE [d:][path]filename
  6. CODE SEGMENT                         ;*************************
  7. ASSUME CS:CODE,DS:CODE               ;*                       *
  8. ORG 100H                             ;*  REMEMBER TO EXE2BIN  *
  9.                                      ;*                       *
  10. START:         JMP BEGINNING         ;*************************
  11.  
  12. ;              DATA AREA
  13. ;              ---------
  14. NOTICE         DB    ' Copyright 1986 Ziff-Davis Publishing Co.'
  15. NOTICE_2       DB    ' Programmed by Michael J. Mefford'
  16. CHAR_COUNT     DW     0
  17. CHAR_CT_CARRY  DW     0
  18. WORDCHAR_CT    DW     0
  19. WORDCHAR_CARRY DW     0
  20. WORD_COUNT     DW     0
  21. SENTENCE_COUNT DW     0
  22. LONG_WORDS     DW     0
  23. INTEGER        DW     0
  24. DECIMAL        DW     0
  25.  
  26. WORD_FLAG      DB     0
  27. SENTENCE_FLAG  DB     0
  28. DISPLAY_FLAG   DB     0
  29.  
  30. ALPA_STRING    DB     ' printable characters.',13,10,'$'
  31. WORD_STRING    DB     ' words.',13,10,'$'
  32. LONG_STRING    DB     ' words with three or more syllables.',13,10,'$'
  33. SENT_STRING    DB     ' sentences.',13,10,'$'
  34. CHAR_STRING    DB     ' avg. characters/word.',13,10,'$'
  35. LENG_STRING    DB     ' avg. words/sentence.',13,10,'$'
  36. FOG_INDEX      DB     13,10,'  Reading index',13,10,'$'
  37. GRADE_LEVEL    DB     ' grade level.',13,10,'$'
  38. DECIMAL_PT     DB     '.$'
  39. CARRY_64K      DB     '65536+$'
  40.  
  41. ;-------------------------------------------------------;
  42. ; Before the file can be parsed, the command line has   ;
  43. ; to be parsed.  Then the file will be opened and read. ;
  44. ;-------------------------------------------------------;
  45.  
  46. BEGINNING:     MOV    DI,80H              ;Point to parameter.
  47.                MOV    BL,[DI]             ;Get parameter length.
  48.                XOR    BH,BH                    ;Zero in high half.
  49.                MOV    BYTE PTR DS:[BX+DI+1],0  ;Convert to ASCIIZ string
  50. NEXT_BYTE:     INC    DI                       ;Point to next byte.
  51.                CMP    BYTE PTR DS:[DI],32      ;Is it a space delimiter?
  52.                JZ     NEXT_BYTE                ;If no, get next byte
  53.                MOV    DX,DI               ;If yes, points to parameter.
  54.                MOV    AX,3D00H            ;Open file
  55.                INT    21H                 ; via DOS.
  56.                JC     EXIT                ;If failed, exit.
  57.                PUSH   AX                  ;If OK, save file handle.
  58.  
  59. READ:          POP    BX                  ;File handle in BX
  60.                PUSH   BX                  ; and save to close file
  61.                MOV    DX,OFFSET BUFFER    ; point to DTA
  62.                MOV    CX,64000            ; ask for 64,000 bytes
  63.                MOV    AH,3FH              ; read from file
  64.                INT    21H                 ; via DOS.
  65.                JC     CLOSE_FILE          ;If failed, close file.
  66.                CMP    AX,0                ;Are we at the end of file?
  67.                JNZ    PARSE               ;If no, parse next batch.
  68.                CMP    WORD_FLAG,0         ;Did the file end with word?
  69.                JZ     GO_DISPLAY          ;If no, go display
  70.                INC    WORD_COUNT          ; else add one to word count.
  71.                CMP    SENTENCE_FLAG,0     ;Did the file end with sentence?
  72.                JZ     GO_DISPLAY          ;If no, go display
  73.                INC    SENTENCE_COUNT      ; else add one to sentence count.
  74. GO_DISPLAY:    CALL   DISPLAY             ;If yes, display results.
  75.  
  76. CLOSE_FILE:    POP    BX                  ;Get file handle
  77.                MOV    AH,3EH              ; and close file
  78.                INT    21H                 ; via DOS
  79.  
  80. EXIT:          INT    20H                 ;We are done, so exit.
  81.  
  82. ;-------------------------------------------------------------;
  83. ; Each byte of the file will be examined and the appropriate  ;
  84. ; counter (character, word, or sentence) will be incremented. ;
  85. ; Long words will be counted as 8 characters or more.         ;
  86. ;-------------------------------------------------------------;
  87.  
  88. PARSE:         MOV    CX,AX               ;Set counter to bytes read.
  89.                MOV    SI,OFFSET BUFFER    ;Point to DTA.
  90.                CLD
  91. GET_CHAR:      LODSB                      ;Get a character.
  92.                AND    AL,7FH              ;Strip Wordstar high bit
  93.                CMP    AL,32               ;Is it below a space character?
  94.                JB     DELIMITER           ;If yes, non printable.
  95.                ADD    CHAR_COUNT,1        ;Add one to character count
  96.                ADC    CHAR_CT_CARRY,0     ; and one if carry.
  97. DELIMITER:     CMP    AL,32               ;Is it a delimiter?
  98.                JA     SENTENCE?           ;If no, is it sentence punctuation?
  99.                CMP    SENTENCE_FLAG,0     ;If yes, is it after sentence punc?
  100.                JZ     WORD?               ;If no, is it at the end of a word?
  101.                INC    SENTENCE_COUNT      ;If yes, increment sentence counter.
  102. WORD?:         CMP    WORD_FLAG,0         ;Is it at the end of a word?
  103.                JNZ    WORD_END            ;If yes, it marks the end of a word.
  104. SENTENCE?:     CMP    AL,'.'              ;Is it a period?
  105.                JZ     SENTENCE            ;If yes, flag as possible sentence.
  106.                CMP    AL,'!'              ;Is it '!'
  107.                JZ     SENTENCE            ;If yes, flag as possible sentence.
  108.                CMP    AL,'?'              ;Is it '?'
  109.                JZ     SENTENCE            ;If yes, flag as possible sentence.
  110.                CMP    AL,'-'              ;Is it '-'
  111.                JZ     NOT_WORD_END        ;If yes, flag as not word end.
  112.                CMP    AL,'0'              ;Is it a zero or above?
  113.                JB     NOT_SENTENCE        ;If no, it's punctuation.
  114.                CMP    AL,'9'              ;Is it a nine or below?
  115.                JBE    GOT_WORD            ;If yes, it's numerical character.
  116.                AND    AL,5FH              ;Capitalize.
  117.                CMP    AL,'A'              ;Is it an 'A' or above?
  118.                JB     NOT_SENTENCE        ;If no, it's punctuation.
  119.                CMP    AL,'Z'              ;Is it a 'Z' or below?
  120.                JA     NOT_SENTENCE        ;If no, it's punctuation.
  121. GOT_WORD:      ADD    WORDCHAR_CT,1       ;If we got here, it's alphanumeric
  122.                ADC    WORDCHAR_CARRY,0    ;so add one to character count.
  123.                MOV    WORD_FLAG,1         ;Flag that we are in a word
  124.                INC    BX                  ; increment char count of word
  125.                JMP    SHORT NOT_SENTENCE  ; and flag not sentence end.
  126. SENTENCE:      MOV    SENTENCE_FLAG,1     ;Flag as possible sentence
  127.                JMP    SHORT NEXT_CHAR     ; and get next character.
  128. WORD_END:      INC    WORD_COUNT          ;Add one to word count.
  129.                CMP    BX,8                ;Is word 8 characters?
  130.                JB     NOT_LONGWORD        ;If no, not a long word
  131.                INC    LONG_WORDS          ;else increment long words
  132. NOT_LONGWORD:  XOR    BX,BX               ; and reset char counter.
  133. NOT_WORD_END:  MOV    WORD_FLAG,0         ;Flag as not in a word.
  134. NOT_SENTENCE:  MOV    SENTENCE_FLAG,0     ;Flag as not possible sentence.
  135. NEXT_CHAR:     LOOP   GET_CHAR            ;Get next character.
  136.                JMP    READ                ;Go read next batch.
  137.  
  138.               ;*************;
  139.               ; Subroutines ;
  140.               ;*************;
  141.  
  142. ;-----------------------------------------------------------------;
  143. ; This subroutine is in charge of displaying each line of output. ;
  144. ;-----------------------------------------------------------------;
  145.  
  146. DISPLAY:       MOV    DL,10               ;First print a linefeed
  147.                MOV    AH,2                ; just to make the output
  148.                INT    21H                 ; pretty.
  149.                CMP    CHAR_CT_CARRY,0     ;Did the char. count overflow?
  150.                JZ     NO_CARRY                 ;If no, display low half
  151.                MOV    DX,OFFSET CARRY_64K      ;If yes, display 64k+
  152.                MOV    AH,9
  153.                INT    21H
  154. NO_CARRY:      MOV    BX,CHAR_COUNT            ;Same with low half
  155.                CALL   NUMBERS                  ;and display.
  156.                MOV    DX,OFFSET ALPA_STRING    ;Display the
  157.                CALL   DISPLAY_TEXT             ;text as well.
  158.  
  159.                MOV    BX,WORD_COUNT       ;Word count into BX
  160.                CALL   NUMBERS                  ;and display.
  161.                MOV    DX,OFFSET WORD_STRING    ;Display the
  162.                CALL   DISPLAY_TEXT             ;text as well.
  163.  
  164.                MOV    BX,LONG_WORDS       ;Long words into BX.
  165.                CALL   NUMBERS                  ;and display.
  166.                MOV    DX,OFFSET LONG_STRING    ;Display the
  167.                CALL   DISPLAY_TEXT             ;text as well.
  168.  
  169.                MOV    BX,SENTENCE_COUNT   ;Sentence count into BX
  170.                CALL   NUMBERS                  ;and display.
  171.                MOV    DX,OFFSET SENT_STRING    ;Display the
  172.                CALL   DISPLAY_TEXT             ;text as well.
  173.  
  174.                MOV    AX,WORDCHAR_CT      ;Character count into AX
  175.                MOV    DX,WORDCHAR_CARRY   ; and carry in high half
  176.                MOV    CX,WORD_COUNT       ; divisor into CX
  177.                DIV    CX                  ; and divide.
  178.                CALL   GET_DECIMAL         ;Convert remainder to decimal
  179.                CALL   DISPLAY_TENTH            ;to display tenths.
  180.                MOV    DX,OFFSET CHAR_STRING    ;Display the
  181.                CALL   DISPLAY_TEXT             ;text as well.
  182.  
  183.                MOV    AX,WORD_COUNT       ;Character count into AX
  184.                XOR    DX,DX               ; and zero in high half
  185.                MOV    CX,SENTENCE_COUNT   ; divisor into CX
  186.                DIV    CX                  ; and divide.
  187.                CALL   GET_DECIMAL         ;Convert remainder to decimal
  188.                CALL   DISPLAY_TENTH            ;to display tenths.
  189.                MOV    DX,OFFSET LENG_STRING    ;Display the
  190.                CALL   DISPLAY_TEXT             ;text as well.
  191.  
  192.                MOV    DX,OFFSET FOG_INDEX      ;Display "Reading index"
  193.                CALL   DISPLAY_TEXT
  194.                MOV    AX,40               ;First multiply long words by 40.
  195.                MUL    LONG_WORDS
  196.                MOV    CX,WORD_COUNT       ;Then divide by word count.
  197.                DIV    CX
  198.                CALL   GET_DECIMAL         ;Convert remainder to decimal.
  199.                PUSH   DECIMAL             ;Save both halves of the number.
  200.                PUSH   INTEGER
  201.                MOV    AX,10               ;Now multiply sentence count by 10
  202.                MUL    SENTENCE_COUNT
  203.                PUSH   AX                  ; and save.
  204.                MOV    AX,4                ;Multiply word count by 4.
  205.                MUL    WORD_COUNT
  206.                POP    CX                  ;Retrieve prior dividend
  207.                DIV    CX                  ; and divide.
  208.                CALL   GET_DECIMAL
  209.                POP    AX                  ;Retrieve rest of index integer
  210.                ADD    INTEGER,AX          ; and add to this half of index.
  211.                POP    AX                  ;Do the same with the decimal.
  212.                ADD    AX,DECIMAL
  213.                CALL   ROUND?              ;See if needs rounding.
  214.                CALL   DISPLAY_TENTH            ;Display the number.
  215.                MOV    DX,OFFSET GRADE_LEVEL    ;Display the
  216.                CALL   DISPLAY_TEXT             ;text as well.
  217.                RET
  218.  
  219. ;------------------------------------------------------------;
  220. ; This subroutine divides to convert hexidecimal to decimal. ;
  221. ;------------------------------------------------------------;
  222.  
  223. NUMBERS:       MOV    CX,10000            ;Get ten thousands by dividing.
  224.                CALL   DIVIDE
  225.                MOV    CX,1000             ;Get thousands by dividing.
  226.                CALL   DIVIDE
  227. TENTHS:        MOV    CX,100              ;Get hundreds by dividing.
  228.                CALL   DIVIDE
  229.                MOV    CX,10               ;Get tens by dividing.
  230.                CALL   DIVIDE
  231.                MOV    CX,1                ;Get ones by dividing.
  232.                CALL   DIVIDE
  233.                MOV    DISPLAY_FLAG,0      ;Reset display flag.
  234.                RET
  235.  
  236. ;------------------------------------------------------------------------;
  237. ; This subroutine does the actual dividing and suppresses leading zeros. ;
  238. ;------------------------------------------------------------------------;
  239.  
  240. DIVIDE:        MOV    AX,BX               ;Number in AX
  241.                XOR    DX,DX               ; and zero in DX
  242.                DIV    CX                  ; divide by CX
  243.                MOV    BX,DX               ; remainder into BX
  244.                MOV    DL,AL               ; and quotient into DL.
  245.                CMP    AL,0                ;Is it zero?
  246.                JZ     FLAG                ;If yes, is a non zero displayed?
  247.                OR     DISPLAY_FLAG,AL     ;If non zero indicate by flag.
  248. FLAG:          CMP    DISPLAY_FLAG,0      ;Non zero number been displayed?
  249.                JNZ    DISP_NUMBER         ;If yes, suppress leading zeros
  250.                MOV    DL,-10H             ; with blanks.
  251.  
  252. DISP_NUMBER:   ADD    DL,30H              ;Convert hexadecimal to decimal
  253.                MOV    AH,2H               ; and display via
  254.                INT    21H                 ; DOS.
  255.                RET
  256.  
  257. ;------------------------------------------------------------;
  258. ; This subroutine displays the text via DOS function call 9. ;
  259. ;------------------------------------------------------------;
  260.  
  261. DISPLAY_TEXT:  MOV    AH,9H               ;Display text string
  262.                INT    21H                 ;via DOS.
  263.                RET
  264.  
  265. ;---------------------------------------------------------------;
  266. ; This subroutine gets the decimal part after integer division. ;
  267. ;---------------------------------------------------------------;
  268.  
  269. GET_DECIMAL:   MOV    INTEGER,AX          ;Save the integer half.
  270.                MOV    AX,10               ;Multiply the remainder by 10.
  271.                MUL    DX
  272.                DIV    CX                  ;Divide by last divisor.
  273.                ADD    DX,DX               ;Double remainder.
  274.                CMP    DX,CX               ;Is it more than half?
  275.                JB     NO_ROUND            ;If no, don't round up
  276.                INC    AX                  ; else add one to decimal.
  277. ROUND?:        CMP    AX,10               ;Is it over ten?
  278.                JB     NO_ROUND            ;If no, don't round up
  279.                SUB    AX,10               ; else subtract one from decimal
  280.                INC    INTEGER             ; and increment the integer.
  281. NO_ROUND:      MOV    DECIMAL,AX          ;Save decimal.
  282.                RET
  283. ;------------------------------------------------------------------;
  284. ; This subroutine displays the integer, decimal point and decimal. ;
  285. ;------------------------------------------------------------------;
  286.  
  287. DISPLAY_TENTH: MOV    BX,INTEGER          ;Retrieve integer and display
  288.                CALL   TENTHS
  289.                MOV    DX,OFFSET DECIMAL_PT     ;Display the decimal point.
  290.                CALL   DISPLAY_TEXT
  291.                MOV    DX,DECIMAL          ;Then display the decimal
  292.                CALL   DISP_NUMBER
  293.                RET
  294.  
  295. BUFFER:                                   ;Data transfer area.
  296.  
  297. CODE ENDS
  298. END  START
  299.