home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine CD 1995 / Archive Magazine CD 1995.iso / discs / prog_disc / volume_5 / issue_08 / boota / C-source / c / UnNum < prev   
Encoding:
Text File  |  1991-12-16  |  21.7 KB  |  577 lines

  1. /* > c.UnNum  - (c) Paul Witheridge - Version 2.00 - 06 Dec 1991     */
  2.  
  3. /*===================================================================*/
  4. /*                                                                   */
  5. /*  UnNum  -  unnumber file                                          */
  6. /*  ------                                                           */
  7. /*                                                                   */
  8. /*  This utility removes line numbers from a file.                   */
  9. /*                                                                   */
  10. /*  If the file is fixed-blocked with a line length of 80 bytes,     */
  11. /*  then columns 73-80 are assumed to be the columns occuppied by    */
  12. /*  the line sequence number.                                        */
  13. /*                                                                   */
  14. /*  If the file is not fixed-blocked with a line length of 80 bytes, */
  15. /*  then the line sequence number is assumed to occuppy columns      */
  16. /*  1-8 of each line.                                                */
  17. /*                                                                   */
  18. /*  The utility checks that all lines are numbered (and that the     */
  19. /*  last line does end with a newline character). If not error       */
  20. /*  messages are issued. If so, the columns containing the line      */
  21. /*  sequence characters are deleted from the file. Any trailing      */
  22. /*  blanks in each line are also deleted.                            */
  23. /*                                                                   */
  24. /*-------------------------------------------------------------------*/
  25. /*                                                                   */
  26. /*  COPYRIGHT NOTICE                                                 */
  27. /*                                                                   */
  28. /*  UnNum is subject to Copyright.                                   */
  29. /*                                                                   */
  30. /*  Permission is granted by the author to any recipient of this     */
  31. /*  material to use and make/disseminate copies of the application   */
  32. /*  provided that no charges are made for doing so (other than to    */
  33. /*  cover any cost of media or postage) and that this notice is      */
  34. /*  included with all copies.                                        */
  35. /*                                                                   */
  36. /*===================================================================*/
  37.  
  38. #include "kernel.h"                     /* ARC specifics             */
  39. #include <ctype.h>                      /* Character handling        */
  40. #include <limits.h>                     /* Implementation limits     */
  41. #include <stddef.h>                     /* Standard definitions      */
  42. #include <stdio.h>                      /* Input/output              */
  43. #include <stdlib.h>                     /* General utilities         */
  44. #include <string.h>                     /* String handling           */
  45. #include "GetDirs.h"                    /* GetDirs header            */
  46. #include "ArgFuncs.h"                   /* Arg functions etc         */
  47. #include "Useful.h"                     /* Useful definitions        */
  48.  
  49. /*-------------------------------------------------------------------*/
  50. /*  Global data declarations and definitions.                        */
  51. /*-------------------------------------------------------------------*/
  52.  
  53. static char flags = '\0' ;              /* Processing flags          */
  54.  
  55.   #define flgfnd 0x01                   /* Found file to process     */
  56.   #define flgovr 0x10                   /* Overwrite mode            */
  57.   #define flgrcs 0x20                   /* Recursive mode            */
  58.   #define flgtst 0x40                   /* Test mode                 */
  59.  
  60. static int filecount = 0 ;              /* Count of files processed. */
  61.  
  62. static const char *argptr = NULL ;      /* Pointer to file spec.     */
  63. static const char *pfxptr = "_" ;       /* Pointer to output prefix  */
  64.  
  65. /*-------------------------------------------------------------------*/
  66. /*  Declare functions local in scope to this file.                   */
  67. /*-------------------------------------------------------------------*/
  68.  
  69. static enum boolean cnvtfunc(           /* Convert function          */
  70.   const char *path,
  71.   direntry *ptr) ;
  72.  
  73. /*===================================================================*/
  74. /*                                                                   */
  75. /*  Main program                                                     */
  76. /*  ------------                                                     */
  77. /*                                                                   */
  78. /*  Analyse arguments. Then call the "GetDirentrys" function to      */
  79. /*  read all the file-names in the specified directory (plus any     */
  80. /*  sub directories). Provide "GetDirentrys" with pointer to         */
  81. /*  function to process the specified files.                         */
  82. /*                                                                   */
  83. /*===================================================================*/
  84.  
  85. int main(
  86.   const int argc,                     /* Number of arguments         */
  87.   const char *const argv[])           /* Array of pointers to args   */
  88. {
  89.   /*-----------------------------------------------------------------*/
  90.   /*  Local definitions.                                             */
  91.   /*-----------------------------------------------------------------*/
  92.  
  93.   int returncode ;
  94.  
  95.   static const char options[] =  /* Used to match option argument    */
  96.   {
  97.     'O',                            /* Overwrite mode                */
  98.     'P',                            /* Output prefix                 */
  99.     'R',                            /* Recursive mode                */
  100.     'T',                            /* Test mode                     */
  101.     '0'                             /* Null byte terminator          */
  102.   } ;
  103.  
  104.   static const char **posval[] = /* Ptrs to ptrs to posit'nal values */ 
  105.   {
  106.     &argptr
  107.   } ;
  108.  
  109.   static const char optflags[] = /* Used to set option flags         */
  110.   {
  111.     flgovr,                         /* Overwrite mode                */
  112.     0,                              /* Output prefix                 */
  113.     flgrcs,                         /* Recursive mode                */
  114.     flgtst,                         /* Test mode                     */
  115.   } ;
  116.  
  117.   static const char **optval[] = /* Ptrs to ptrs to option values    */
  118.   {
  119.     NULL,                           /* No value allowed              */
  120.     &pfxptr,                        /* Output file prefix            */
  121.     NULL,                           /* No value allowed              */
  122.     NULL,                           /* No value allowed              */
  123.   } ;
  124.  
  125.   static const char helpdata[] = /* Help text to be displayed        */
  126.  
  127.     "Unnum removes line-numbers from cols 73-80 of card-image "
  128.     "text files or from cols 1-8 of other text files (i.e. "
  129.     "files with standard IBM S/370 line sequence numbers).\x1f"
  130.     "\x1f"
  131.     "WARNING:\x01This utility converts files IN-PLACE if the "
  132.     "'-o' option is used to replace the input text "
  133.     "file with the output unnumbered file.\x1f"
  134.     "\x1f"
  135.     "Syntax:\x01*Unnum  [path.]object  [options]\x1f"
  136.     "\x1f"
  137.     "object:\x01Specifies one of the following:\x1f"
  138.     "\x01(a) a single non-wildcarded file name\x1f"
  139.     "\x01(b) a single non-wildcarded directory name\x1f"
  140.     "\x01(c) a wildcarded name.\x1f"
  141.     "\x1f"
  142.     "\x01In case (a) the file is unnumbered provided "
  143.     "that it has a file-type of TEXT, contains no "
  144.     "unprintable characters and has decimal digits "
  145.     "in the correct sequence number columns.\x1f"
  146.     "\x1f"
  147.     "\x01In case (b) all files in the specified "
  148.     "directory which meet the above conditions are "
  149.     "unnumbered. If the RECURSION option is specified "
  150.     "all files in all subdirectories are also "
  151.     "unnumbered.\x1f"
  152.     "\x1f"
  153.     "\x01In case (c) all matching files which meet the "
  154.     "above conditions are unnumbered. If no matching "
  155.     "files are found, then the first matching "
  156.     "directory name is taken and all eligible files "
  157.     "therein are unnumbered. If the RECURSION option "
  158.     "is specified, all matching files are unnumbered, "
  159.     "plus all files in all subdirectories.\x1f"
  160.     "\x1f"
  161.     "\x01In all cases, only files which have a filetype "
  162.     "of TEXT (hex FFF), which contain no unprintable "
  163.     "characters (except newline - hex 0A) and which "
  164.     "contain valid decimal digits in the correct "
  165.     "sequence number columns, will be unnumbered.\x1f"
  166.     "\x1f"
  167.     "path:\x01Specifies the directory to be searched for "
  168.     "the object file/directory. If omitted the current "
  169.     "directory is searched.\x1f"
  170.     "\x1f"
  171.     "options:\x01Specifies processing options which can be "
  172.     "one or more ofthe following:\x1f"
  173.     "\x1f"
  174.     "\x01-o\x02-\x03OVERWRITE mode; output file will have "
  175.     "same name and will replace input file.\x1f"
  176.     "\x1f"
  177.     "\x01-p xxx\x02-\x03specify PREFIX which will be used to "
  178.     "create name for output file if '-o' is not specified; "
  179.     "'xxx' can be one or more characters including directory "
  180.     "specification (e.g. 'unnumdir.'); if not specified a "
  181.     "default of '_' is used.\x1f"
  182.     "\x1f"
  183.     "\x01-r\x02-\x03RECURSION mode which causes all eligible "
  184.     "files in all subdirectories to be unnumbered.\x1f"
  185.     "\x1f"
  186.     "\x01-t\x02-\x03TEST mode; a list of files to be converted "
  187.     "is displayed but no output is actually written; useful for "
  188.     "checking when specifying a directory or wildcarded filename.\x1f"
  189.     "\x1f"
  190.     "UnNum - copyright Paul Witheridge, 1991\x1f"
  191.     "\x1f" ;
  192.  
  193.   static const unsigned char helptabs[] =  /* Help text tab settings */
  194.   {
  195.     1,10,17,19
  196.   } ;
  197.  
  198.   /*-----------------------------------------------------------------*/
  199.   /*  Executable statements                                          */
  200.   /*-----------------------------------------------------------------*/
  201.  
  202.   puts("\nUnnum Version 2.00 - 03 December 1991\n") ;
  203.  
  204.   /*-----------------------------------------------------------------*/
  205.   /*  Analyse arguments for file-name and option flags.              */
  206.   /*-----------------------------------------------------------------*/
  207.  
  208.   analargs(argc,argv,1,posval,options,&flags,optflags,optval) ;
  209.  
  210.   /*-----------------------------------------------------------------*/
  211.   /*  Set paged scrolling mode                                       */
  212.   /*-----------------------------------------------------------------*/
  213.  
  214.   _kernel_oswrch(12) ;
  215.   _kernel_oswrch(14) ;
  216.  
  217.   puts(" PRESS SHIFT KEY TO ALLOW WINDOW TO SCROLL\n") ;
  218.   
  219.   /*-----------------------------------------------------------------*/
  220.   /*  If no file name operand just display help text.                */
  221.   /*-----------------------------------------------------------------*/
  222.  
  223.   if ( argptr == NULL )
  224.   {
  225.     displaytext(helpdata,helptabs) ;
  226.     _kernel_oswrch(15) ;
  227.     return 0 ;
  228.   }
  229.  
  230.   /*-----------------------------------------------------------------*/
  231.   /*  If TEST MODE issue message.                                    */
  232.   /*-----------------------------------------------------------------*/
  233.  
  234.   if ( flags & flgtst )
  235.   {
  236.     puts("TEST MODE (files will be identified, not converted).\n") ;
  237.   }
  238.  
  239.   /*-----------------------------------------------------------------*/
  240.   /*  Invoke GetDirs function to read the directory entry(s) of the  */
  241.   /*  file(s) to be processed. Pass it a pointer of a processing     */
  242.   /*  function to be called.                                         */
  243.   /*-----------------------------------------------------------------*/
  244.  
  245.   returncode = 4 ;
  246.  
  247.   if ( getdirentrys(argptr,
  248.        ( flags & flgrcs ? RECURSE_ALWAYS : RECURSE_ONCE ),cnvtfunc) )
  249.   {
  250.     if ( flags & flgfnd )
  251.     {
  252.       printf("\n%d text file(s) ",filecount) ;
  253.       if ( flags & flgtst )
  254.       {
  255.         printf("would be ") ;
  256.       }
  257.       puts("unnumbered.\n") ;
  258.       returncode = 0 ;
  259.     }
  260.     else
  261.     {
  262.       printf("No text files found matching '%s'\n",argptr) ;
  263.       beep() ;
  264.     }
  265.   }
  266.   
  267.   /*-----------------------------------------------------------------*/
  268.   /*  Return to caller. All done.                                    */
  269.   /*-----------------------------------------------------------------*/
  270.  
  271.   _kernel_oswrch(15) ;
  272.   return returncode ;
  273. }
  274.  
  275. /*===================================================================*/
  276. /*                                                                   */
  277. /*  cnvtfunc  -  perform actual file conversion                      */
  278. /*  --------                                                         */
  279. /*                                                                   */
  280. /*  This function is called by the "getdirentrys" function for each  */
  281. /*  file-name that it encounters.                                    */
  282. /*                                                                   */
  283. /*  Only files which have a filetype of "text" (0xFFF) will be       */
  284. /*  processed.                                                       */
  285. /*                                                                   */
  286. /*===================================================================*/
  287.  
  288. static enum boolean cnvtfunc(
  289.   const char *path,                   /* Pointer to path name.       */
  290.   direntry *ptr)                      /* Pointer to direntry info.   */
  291. {
  292.   char *infile ;                      /* Ptr to path + leafname      */
  293.   char *oufile ;                      /* Ptr tp path + leafname      */
  294.   int result ;                        /* Result from OS-File SWI     */
  295.   enum boolean cardimage ;            /* Cardimage format switch     */
  296.   char *workarea ;                    /* Ptr to start of work area   */
  297.   char *workend ;                     /* Ptr to end of work area     */
  298.   char *lineptr ;                     /* Working ptr to line start   */
  299.   char *endlineptr ;                  /* Working ptr to line end     */
  300.   char *cptr ;                        /* Working ptr to next char    */
  301.   char *optr ;                        /* Ptr to next output char     */
  302.  
  303.   _kernel_osfile_block osfileblock ;  /* OS File parameter block     */
  304.  
  305.   /*-----------------------------------------------------------------*/
  306.   /*  Executable statements                                          */
  307.   /*                                                                 */
  308.   /*  Return immediately if not a text file                          */
  309.   /*-----------------------------------------------------------------*/
  310.  
  311.   if ( ptr->type != 0xFFF )
  312.   {
  313.     return TRUE ;
  314.   }
  315.  
  316.   /*-----------------------------------------------------------------*/
  317.   /*  Create input and output filespecs                              */
  318.   /*-----------------------------------------------------------------*/
  319.   
  320.   if ( ( infile = malloc(2 * (strlen(path) + strlen(ptr->name) + 1)
  321.                          + strlen(pfxptr) ) ) == NULL )
  322.   {
  323.     puts("Out of memory") ;
  324.     return FALSE ;
  325.   } 
  326.   
  327.   oufile = infile + sprintf(infile,"%s%s",path,ptr->name) + 1 ;
  328.   sprintf(oufile,"%s%s%s",path,flags & flgovr ? "" : pfxptr,ptr->name) ;
  329.   
  330.   /*-----------------------------------------------------------------*/
  331.   /*  If test mode display heading on first time through             */
  332.   /*-----------------------------------------------------------------*/
  333.  
  334.   if ( (flags & flgtst) && !(flags & flgfnd) )
  335.   {
  336.     puts("The following files would be unnumbered:\n") ;
  337.   }
  338.  
  339.   flags |= flgfnd ;
  340.  
  341.   /*-----------------------------------------------------------------*/
  342.   /*  Check input file has non-zero length                           */
  343.   /*-----------------------------------------------------------------*/
  344.  
  345.   if ( ptr->length == 0 )
  346.   {
  347.     printf("'%s' is empty\n",infile) ;
  348.   }
  349.  
  350.   /*-----------------------------------------------------------------*/
  351.   /*  Allocate memory for file and load file                         */
  352.   /*-----------------------------------------------------------------*/
  353.  
  354.   if ( (workarea = malloc((ptr->length)+1) ) == NULL )
  355.   {
  356.     printf("'%s%s' too large to load",path,ptr->name) ;
  357.     goto error4 ;
  358.   }
  359.  
  360.   workend = workarea + ptr->length ;
  361.  
  362.   osfileblock.load  = (int)workarea ;
  363.   osfileblock.exec  = 0 ;
  364.   result = _kernel_osfile(16,infile,&osfileblock) ;
  365.  
  366.   if (result == _kernel_ERROR)
  367.   {
  368.     printf("'%s' load failed - %s\n",infile,
  369.           _kernel_last_oserror()->errmess) ;
  370.     goto error3 ;
  371.   }
  372.  
  373.   /*-----------------------------------------------------------------*/
  374.   /*  If file contains any CRLF combinations convert these to        */
  375.   /*  Archimedes newline characters (linefeed only)                  */
  376.   /*-----------------------------------------------------------------*/
  377.  
  378.   *workend = 0 ;
  379.  
  380.   for ( cptr = optr = workarea ; cptr < workend ; cptr++, optr++ )
  381.   {
  382.     if ( *cptr == 0x1A )
  383.     {
  384.       break ;
  385.     }
  386.     if ( *cptr == 0x0d && *(cptr+1) == 0x0A )
  387.     {
  388.       cptr++;
  389.     }
  390.     *optr = *cptr ;
  391.   }
  392.  
  393.   workend = optr ;
  394.   
  395.   /*-----------------------------------------------------------------*/
  396.   /*  Check for fixed-blocked 80 byte lines (cardimage file)         */
  397.   /*-----------------------------------------------------------------*/
  398.  
  399.   *workend = '\n' ;
  400.   lineptr = workarea ;
  401.   cardimage = TRUE ;
  402.  
  403.   while ( lineptr < workend )
  404.   {
  405.     endlineptr = memchr(lineptr,'\n',INT_MAX) ;
  406.     if ( endlineptr - lineptr != 80 )
  407.     {
  408.       cardimage = FALSE ;
  409.     }
  410.     lineptr = endlineptr + 1 ;
  411.   }
  412.  
  413.   /*-----------------------------------------------------------------*/
  414.   /*  Error message if no newline at end of file                     */
  415.   /*-----------------------------------------------------------------*/
  416.  
  417.   if ( lineptr != workend )
  418.   {
  419.     printf("'%s' not valid text file - "
  420.            "does not end with newline character\n",infile) ;
  421.     goto noconversion ;
  422.   }
  423.  
  424.   /*-----------------------------------------------------------------*/
  425.   /*  Process cardimage file - delete cols 73-80 & trailing blanks   */
  426.   /*-----------------------------------------------------------------*/
  427.  
  428.   optr = workarea ;
  429.  
  430.   if ( cardimage )
  431.   {
  432.     for ( lineptr = workarea ;
  433.           lineptr < workend ;
  434.           lineptr = endlineptr + 1 )
  435.     {
  436.       endlineptr = lineptr + 72 ;
  437.       for ( cptr = lineptr ; cptr < endlineptr ; cptr++ )
  438.       {
  439.         if ( !isprint(*cptr) )
  440.         {
  441.           printf("'%s' not valid text file - "
  442.                  "contains unprintable characters\n",
  443.                  infile) ;
  444.           goto noconversion ;
  445.         }
  446.       }
  447.       endlineptr = lineptr + 80 ;
  448.       for ( ; cptr < endlineptr ; cptr++ )
  449.       {
  450.         if ( !isdigit(*cptr) )
  451.         {
  452.           printf("'%s' not numbered file (cols 73-80)\n",
  453.                  infile) ;
  454.           goto noconversion ;
  455.         }
  456.       }
  457.       for ( cptr = lineptr + 71 ;
  458.             cptr >= lineptr && *cptr == ' ' ;
  459.             cptr-- ) ;
  460.       for ( ; lineptr <= cptr ; lineptr++ )
  461.       {
  462.         *(optr++) = *lineptr ;
  463.       }
  464.       *(optr++) = '\n' ;
  465.     }
  466.   }
  467.  
  468.   /*-----------------------------------------------------------------*/
  469.   /*  Process non-cardimage file. Delete cols 1-8 plus any           */
  470.   /*  trailing blanks                                                */
  471.   /*-----------------------------------------------------------------*/
  472.  
  473.   else
  474.   {
  475.     lineptr = workarea ;
  476.  
  477.     while ( lineptr < workend )
  478.     {
  479.       endlineptr = lineptr + 8 ;
  480.       for ( cptr = lineptr ;
  481.             cptr < endlineptr ;
  482.             cptr++ )
  483.       {
  484.         if ( !isdigit(*cptr) )
  485.         {
  486.           printf("'%s' not numbered file (cols 1-8)\n",
  487.                  infile) ;
  488.           goto noconversion ;
  489.         }
  490.       }
  491.       lineptr = endlineptr ;
  492.       for ( ; *endlineptr != '\n' ; endlineptr++ )
  493.       {
  494.         if ( !isprint(*cptr) )
  495.         {
  496.           printf("'%s' not valid text file - "
  497.                  "contains unprintable characters\n",
  498.                  infile) ;
  499.           goto noconversion ;
  500.         }
  501.       }
  502.       for ( cptr = endlineptr - 1 ;
  503.             cptr >= lineptr && *cptr == ' ' ;
  504.             cptr-- ) ;
  505.       for ( ; lineptr <= cptr ; lineptr++ )
  506.       {
  507.         *(optr++) = *lineptr ;
  508.       }
  509.       *(optr++) = '\n' ;
  510.  
  511.       lineptr = endlineptr + 1 ;
  512.     }
  513.   }
  514.  
  515.   /*-----------------------------------------------------------------*/
  516.   /*  If not test mode, save modified file                           */
  517.   /*-----------------------------------------------------------------*/
  518.  
  519.   if ( !(flags & flgtst) )
  520.   {
  521.     osfileblock.start = (int)workarea ;
  522.     osfileblock.end   = (int)optr ;
  523.     osfileblock.load  = 0xfff ;
  524.  
  525.     result = _kernel_osfile(10,oufile,&osfileblock) ;
  526.  
  527.     if (result == _kernel_ERROR)
  528.     {
  529.       printf("'%s' save failed - %s\n",oufile,
  530.              _kernel_last_oserror()->errmess);
  531.       goto error3 ;
  532.     }
  533.   }
  534.  
  535.   /*-----------------------------------------------------------------*/
  536.   /*  Valid numbered text file - bump file count                     */
  537.   /*-----------------------------------------------------------------*/
  538.   
  539.   filecount++ ;
  540.  
  541.   /*-----------------------------------------------------------------*/
  542.   /*  Display file name (plus "unnumbered" if not test mode)         */
  543.   /*-----------------------------------------------------------------*/
  544.  
  545.   printf("'%s'",infile) ;
  546.   if ( !(flags & flgtst) )
  547.   {
  548.     printf(" unnumbered") ;
  549.     if ( !(flags & flgovr) )
  550.     {
  551.       printf(" and saved as '%s'",oufile) ;
  552.     }
  553.   }
  554.   putchar('\n') ;
  555.  
  556.   /*-----------------------------------------------------------------*/
  557.   /*  Free work area and return with good completion code            */
  558.   /*-----------------------------------------------------------------*/
  559.  
  560.   noconversion: free(workarea) ;
  561.                 free(infile) ;
  562.  
  563.   return TRUE ;
  564.  
  565.   /*-----------------------------------------------------------------*/
  566.   /*  Error exits                                                    */
  567.   /*-----------------------------------------------------------------*/
  568.  
  569.   error3: free(workarea) ;
  570.   error4: free(infile) ;
  571.           beep() ;
  572.  
  573.   return FALSE ;
  574. }
  575.  
  576. /*=====================================================================*/
  577.