/[dtapublic]/projs/dtats/trunk/projs/2018/20180718_ets_ifsfscan/c_main.c
ViewVC logotype

Diff of /projs/dtats/trunk/projs/2018/20180718_ets_ifsfscan/c_main.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 164 by dashley, Sat Jul 7 20:34:59 2018 UTC revision 199 by dashley, Sun Jul 15 03:07:20 2018 UTC
# Line 1  Line 1 
1  //$Header$  //$Header$
2    //{f0d952cc-7499-4d5c-9f46-d0b509c5701c}
3  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
4  //This file is part of "ifsfscan", a program for identifying and correcting gross formatting  //Copyright (c) 2018, David T. Ashley
5  //anomalies in source files.  //
6  //-------------------------------------------------------------------------------------------------  //This file is part of "ifsfscan", a program for identifying gross formatting anomalies in source
7  //This source code and any program in which it is compiled/used is provided under the MIT License,  //files (Windows/ASCII text files only).
8    //
9    //This source code and any program in which it is compiled/used is licensed under the MIT License,
10  //reproduced below.  //reproduced below.
11  //-------------------------------------------------------------------------------------------------  //
12  //Permission is hereby granted, free of charge, to any person obtaining a copy of  //Permission is hereby granted, free of charge, to any person obtaining a copy of
13  //this software and associated documentation files(the "Software"), to deal in the  //this software and associated documentation files(the "Software"), to deal in the
14  //Software without restriction, including without limitation the rights to use,  //Software without restriction, including without limitation the rights to use,
# Line 18  Line 21 
21  //  //
22  //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE  //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25  //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# Line 26  Line 29 
29  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
30  #include <stdio.h>  #include <stdio.h>
31  #include <stdlib.h>  #include <stdlib.h>
32    #include <string.h>
33    #include <tchar.h>
34    #include <time.h>
35    #include <windows.h>
36    
37    
38    #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR    ('-')
39    #define FCMIOF_LINE_LEN                   (78)
40    
41    //The last column allowed for a characters below is Column 82 (or it will be
42    //less than aesthetic).
43    const char * const license_preamble[] =
44    {
45       "ifsfscan, (c) 2018 David T. Ashley (dashley@gmail.com)",
46       "This program's source files, executable files, and all other related files",
47       "(such as Visual Studio project files) are licensed under \"The MIT License\",",
48       "reproduced below."
49    };
50    
51  static const char * const license_text[] =  const char * const license_text[] =
52  {  {
53          "Permission is hereby granted, free of charge, to any person obtaining a copy of",          "Permission is hereby granted, free of charge, to any person obtaining a copy",
54          "this software and associated documentation files(the \"Software\"), to deal in the",          "of this software and associated documentation files(the \"Software\"), to deal",
55          "Software without restriction, including without limitation the rights to use,",          "in the Software without restriction, including without limitation the rights",
56          "copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the",          "to use, copy, modify, merge, publish, distribute, sublicense, and / or sell",
57          "Software, and to permit persons to whom the Software is furnished to do so,"          "copies of the Software, and to permit persons to whom the Software is",
58          "subject to the following conditions :",          "furnished to do so, subject to the following conditions:",
59          "",          "",
60          "The above copyright notice and this permission notice shall be included in all",          "The above copyright notice and this permission notice shall be included in",
61          "copies or substantial portions of the Software.",          "all copies or substantial portions of the Software.",
62          "",          "",
63          "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",          "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
64          "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",          "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
65          "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE",          "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE",
66          "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",          "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
67          "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",          "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
68          "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE"          "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
69          "SOFTWARE."          "SOFTWARE."
70  };  };
71    
72  static const char * const prog_desc_text[] =  const char * const prog_desc_text[] =
73  {  {
74          "ifsfscan (mnemonic: Ill-Formed Source File SCAN) is a program for detecting and",          "ifsfscan (mnemonic: Ill-Formed Source File SCAN) is a program for detecting",
75          "correcting gross formatting errors in source files.  The errors detected and",          "gross formatting errors in source files (Windows/ASCII text files only).  The",
76          "corrected include non-ASCII characters, tab characters, trailing whitespace on",     "errors detected are non-ASCII characters, tab characters, abnormal",
77          "lines, and other errors.",     "end-of-line characters, and trailing whitespace on lines.",
78  };  };
79    
80  static const char * const prog_help_text[] =  const char * const prog_help_text[] =
81  {  {
82          "Usage:  ifsfscan <options> <files_no_wildcards>",          "Usage:  ifsfscan [filename_or_wildcard [filename_or_wildcard [...]]]",
         "",  
         "Options:",  
         "   -fixall",  
         "      Fixes all known formatting issues non-interactively.  For users who",  
         "      understand the program's behavior, this is the most common option used.",  
         "   -fixnone (default)",  
         "      Identifies formatting issues, but does make any corrections.",  
83          "",          "",
84          "Notes:",          "Notes:",
85          "   ( 1) : THIS PROGRAM CAN DESTROY DATA.  This program does not make backup",     "   (1) : Wildcards (\"*\", \"?\") are processed by Windows, so Windows is",
86          "          files.  If this program were used to make \"corrections\" on a binary",     "         the arbiter of which wildcards are accepted and how they expand.",
87          "          file, the file would likely be irreparably corrupted.",     "   (2) : This program never writes to a file, so it cannot destroy data",
88          "   ( 2) : This program does not process wildcards.",          "         (except, possibly, by stdout output redirected to a file).",
89          "   ( 3) : This program is limited by available memory.  This program parses a",          "   (3) : This program accepts no options (like \"-help\" or \"-verbose\").",
90          "          source file, writing the corrected file to a RAM buffer, then finally",          "   (4) : This program accepts only Windows line endings (13-10).",
91          "          overwrites the source file from the RAM buffer.  The practical limit",          "         This program is incompatible with *nix and *nix files.",
92          "          for the size of the file that can be corrected using this program is",     "   (5) : This program accepts only the ASCII character set (it will not",
93          "          probably a couple gigabytes.",     "         process UTF-8 or any other encodings).",
         "   ( 4) : The license of this program does not prohibit copying the source code",  
         "          to another version control repository or simply \"stealing\" the",  
         "          program and source code for any other use.  The MIT License is a very",  
         "          unrestrictive open-source license."  
94  };  };
95    
   
96  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
97  //  T E R M I N A T I O N    F U N C T I O N S  //  T E R M I N A T I O N    F U N C T I O N S
98  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
99  static void CCMFATAL_fatal(const char *desc, const char *file, size_t line)  void CCMFATAL_fatal(const char *desc, const char *file, size_t line)
100  {  {
101       printf("\n");
102          printf("Fatal error.  Must terminate execution.\n");          printf("Fatal error.  Must terminate execution.\n");
103          printf("File: %s, Line: %zu.\n", file, line);          printf("File: %s, Line: %zu.\n", file, line);
104          printf("Error description: %s\n", desc);          printf("Error description: %s\n", desc);
# Line 98  static void CCMFATAL_fatal(const char *d Line 108  static void CCMFATAL_fatal(const char *d
108  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
109  //  A S S E R T I O N    F U N C T I O N S  //  A S S E R T I O N    F U N C T I O N S
110  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
111    void USERASSERT_assert(int assertion, const char *file, size_t line)
112    {
113       if (! assertion)
114       {
115          printf("\n");
116          printf("Assertion failed.  It is necessary to use the source code to diagnose\n");
117          printf("and resolve this error.\n");
118          printf("File: %s, Line: %zu.\n", file, line);
119          exit(4);  //Error code 4 for error termination.
120       }
121    }
122    
123  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
124  //  M E M O R Y    A L L O C A T I O N    F U N C T I O N S  //  M E M O R Y    A L L O C A T I O N    F U N C T I O N S
# Line 118  void *CCMALLOC_malloc(size_t size) Line 139  void *CCMALLOC_malloc(size_t size)
139                          __LINE__);                          __LINE__);
140          }          }
141    
142       memset(rv, 0, size);
143    
144          return(rv);          return(rv);
145  }  }
146    
# Line 134  void *CCMALLOC_calloc(size_t num, size_t Line 157  void *CCMALLOC_calloc(size_t num, size_t
157                          __LINE__);                          __LINE__);
158          }          }
159    
160       memset(rv, 0, size);
161    
162          return(rv);          return(rv);
163  }  }
164    
# Line 159  void CCMALLOC_free(void *memblock) Line 184  void CCMALLOC_free(void *memblock)
184          free(memblock);          free(memblock);
185  }  }
186    
187  #if 0  //--------------------------------------------------------------------------------
188    //  C H A R A C T E R    F U N C T I O N S
189    //--------------------------------------------------------------------------------
190  int CHARFUNC_digit_to_val(char digit)  int CHARFUNC_digit_to_val(char digit)
191  {  {
192          switch (digit)          switch (digit)
# Line 190  int CHARFUNC_digit_to_val(char digit) Line 216  int CHARFUNC_digit_to_val(char digit)
216          }          }
217  }  }
218    
   
219  char CHARFUNC_nibble_to_lc_hex_digit(int nibble)  char CHARFUNC_nibble_to_lc_hex_digit(int nibble)
220  {  {
221          switch (nibble & 0x0F)          switch (nibble & 0x0F)
# Line 244  char CHARFUNC_nibble_to_lc_hex_digit(int Line 269  char CHARFUNC_nibble_to_lc_hex_digit(int
269                  return('f');                  return('f');
270                  break;                  break;
271          default:          default:
272                  assert(0);        USERASSERT_assert(0, __FILE__, __LINE__);
273                  return('?');                  return('?');
274                  break;                  break;
275          }          }
276  }  }
277    
   
278  void CHARFUNC_int_to_lc_hex_rev(int arg, char *s)  void CHARFUNC_int_to_lc_hex_rev(int arg, char *s)
279  {  {
280          int i;          int i;
281    
282          assert(s != NULL);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
283    
284          for (i = 0; i<8; i++)     for (i = 0; i<8; i++)
285          {          {
286                  s[i] = CHARFUNC_nibble_to_lc_hex_digit(arg);                  s[i] = CHARFUNC_nibble_to_lc_hex_digit(arg);
287                  arg >>= 4;                  arg >>= 4;
288          }          }
289  }  }
290    
291  #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR    ('-')  //--------------------------------------------------------------------------------
292  #define FCMIOF_LINE_LEN                   (78)  //  S T R I N G    A N D    C H A R A C T E R    A R R A Y    F U N C T I O N S
293    //--------------------------------------------------------------------------------
294    int STRING_contains_wildcard(const char *s)
295    {
296       if (strchr(s, '?') != NULL)
297          return(1);
298       else if (strchr(s, '*') != NULL)
299          return(1);
300       else
301          return(0);
302    }
303    
304    int STRING_is_longer_than_maxpath(const char *s)
305    {
306       if (_MAX_PATH <= 5)
307          return(1);
308       else if (strlen(s) > (_MAX_PATH - 5))
309          return(1);
310       else
311          return(0);
312    }
313    
314    int STRING_contains_terminating_backslash(const char *s)
315    {
316       size_t i;
317    
318       i = strlen(s);
319    
320  //08/16/01:  Visual inspection OK.     if (i == 0)
321       {
322          return(0);
323       }
324       else
325       {
326          do
327          {
328             i--;
329             if (s[i] == '\\')
330                return(1);
331             else if ((s[i] != ' ') && (s[i] != '\t'))
332                return(0);
333          } while (i != 0);
334          return(0);
335       }
336    }
337    
338    const char *STRING_vcinfo(size_t which)
339    {
340       static const char * const vcinfo[] =
341       {
342          "$HeadURL$",
343          "$Date$",
344          "$Revision$",
345          "$Author$",
346          "Project GUID:       {f7d7586a-557c-43cb-bec5-b49765d96a5d}",
347          "c_main.c GUID:      {f0d952cc-7499-4d5c-9f46-d0b509c5701c}",
348          "ifsfscan.cpp GUID:  {2abd4437-101c-49eb-99ac-c1174f55b626}",
349       };
350    
351       if (which < (sizeof(vcinfo) / sizeof(vcinfo[0])))
352          return(vcinfo[which]);
353       else
354          return(NULL);
355    }
356    
357    //--------------------------------------------------------------------------------
358    //  F O R M A T T E D    O U T P U T    F U N C T I O N S
359    //--------------------------------------------------------------------------------
360  int FCMIOF_get_line_len(void)  int FCMIOF_get_line_len(void)
361  {  {
362          return(FCMIOF_LINE_LEN);          return(FCMIOF_LINE_LEN);
363  }  }
364    
   
 //08/16/01:  Visual inspection OK.  
365  void FCMIOF_stream_repchar(FILE *s, char c, unsigned n)  void FCMIOF_stream_repchar(FILE *s, char c, unsigned n)
366  {  {
367          assert(s != NULL);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
368    
369          while (n--)          while (n--)
370                  fprintf(s, "%c", c);                  fprintf(s, "%c", c);
371  }  }
372    
   
 //08/16/01:  Visual inspection OK.  
373  void FCMIOF_repchar(char c, unsigned n)  void FCMIOF_repchar(char c, unsigned n)
374  {  {
375          while (n--)          while (n--)
376                  printf("%c", c);                  printf("%c", c);
377  }  }
378    
   
 //08/16/01:  Visual inspection OK.  
379  void FCMIOF_hline(void)  void FCMIOF_hline(void)
380  {  {
381          FCMIOF_repchar(FCMIOF_HORIZONTAL_BAR_SEP_CHAR, FCMIOF_LINE_LEN);          FCMIOF_repchar(FCMIOF_HORIZONTAL_BAR_SEP_CHAR, FCMIOF_LINE_LEN);
382          printf("\n");          printf("\n");
383  }  }
384    
   
 //08/16/01:  Visual inspection OK.  
385  void FCMIOF_stream_hline(FILE *s)  void FCMIOF_stream_hline(FILE *s)
386  {  {
387          assert(s != NULL);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
388    
389          FCMIOF_stream_repchar(s, FCMIOF_HORIZONTAL_BAR_SEP_CHAR, FCMIOF_LINE_LEN);          FCMIOF_stream_repchar(s, FCMIOF_HORIZONTAL_BAR_SEP_CHAR, FCMIOF_LINE_LEN);
390          fprintf(s, "\n");          fprintf(s, "\n");
391  }  }
392    
   
 //08/16/01:  Visual inspection OK.  
393  void FCMIOF_stream_bannerheading(FILE *f,  void FCMIOF_stream_bannerheading(FILE *f,
394          char *s,          char *s,
395          int n_extra_lines)          int n_extra_lines)
# Line 330  void FCMIOF_stream_bannerheading(FILE *f Line 408  void FCMIOF_stream_bannerheading(FILE *f
408    
409          /* Check the file pointer, string pointer, and other par.          /* Check the file pointer, string pointer, and other par.
410          */          */
411          assert(f != NULL);     USERASSERT_assert(f != NULL, __FILE__, __LINE__);
412          assert(s != NULL);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
413          assert(n_extra_lines >= 0);     USERASSERT_assert(n_extra_lines >= 0, __FILE__, __LINE__);
414    
415          /* Print the right number of solid lines of asterisks to the          /* Print the right number of solid lines of asterisks to the
416          ** standard output.          ** standard output.
# Line 385  void FCMIOF_stream_bannerheading(FILE *f Line 463  void FCMIOF_stream_bannerheading(FILE *f
463          }          }
464  }  }
465    
   
 //08/16/01:  Visual inspection OK.  
466  void FCMIOF_bannerheading(char *s, int n_extra_lines)  void FCMIOF_bannerheading(char *s, int n_extra_lines)
467  {  {
468          assert(s != NULL);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
469          assert(n_extra_lines >= 0);     USERASSERT_assert(n_extra_lines >= 0, __FILE__, __LINE__);
470    
471          FCMIOF_stream_bannerheading(stdout, s, n_extra_lines);          FCMIOF_stream_bannerheading(stdout, s, n_extra_lines);
472  }  }
473    
   
474  void FCMIOF_time_stream(FILE *s, time_t ltime)  void FCMIOF_time_stream(FILE *s, time_t ltime)
475  {  {
476          char *p;          char *p;
477    
478          assert(s != NULL);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
479    
480          time(&ltime);          time(&ltime);
481    
# Line 425  void FCMIOF_time_stream(FILE *s, time_t Line 500  void FCMIOF_time_stream(FILE *s, time_t
500          }          }
501  }  }
502    
503  #endif  int is_legal_non_eol_character(char c)
504    {
505       if ((c >= 32) && (c <= 126))
506          return(1);
507       else
508          return(0);
509    }
510    
511    int is_illegal_non_eol_character(char c)
512    {
513       if (((c < 32) || (c > 126)) && (c != 13) && (c != 10))
514          return(1);
515       else
516          return(0);
517    }
518    
519    int is_tab(char c)
520    {
521       if (c == 9)
522          return(1);
523       else
524          return(0);
525    }
526    
527    int is_cr(char c)
528    {
529       if (c == 13)
530          return(1);
531       else
532          return(0);
533    }
534    
535    int is_lf(char c)
536    {
537       if (c == 10)
538          return(1);
539       else
540          return(0);
541    }
542    
543    void emit_human_friendly_llu(unsigned long long arg)
544    {
545       size_t i, len;
546       char buffer[100];
547    
548       sprintf(buffer, "%llu", arg);
549       len = strlen(buffer);
550    
551       for (i = 0; i < len; i++)
552       {
553          printf("%c", buffer[i]);
554          if (((len-i-1) != 0) && (((len - i - 1) % 3) == 0))
555             printf(",");
556       }
557    }
558    
559    void emit_file_pos_3tuple(unsigned long long line, unsigned long long col, unsigned long long offset)
560    {
561       printf("      Line: ");
562       emit_human_friendly_llu(line);
563       printf(", Col: ");
564       emit_human_friendly_llu(col);
565       printf(", Offset: ");
566       emit_human_friendly_llu(offset);
567       printf("\n");
568    }
569    
570    void process_opened_handle(FILE *f)
571    {
572       unsigned long long char_no;
573       unsigned long long line_no;
574       unsigned long long col_no;
575       enum {PST_LINE, PST_CR_FOUND, PST_LF_FOUND} state = PST_LINE;
576       int exit_flag = 0;
577       char in_c, prev_c;
578       unsigned char in_uc;
579       int in_i;
580      
581       in_i = fgetc(f);
582    
583       if (in_i == EOF)
584       {
585          //Zero-length file or error.  Because this tool isn't critical, no need to figure out which, exactly.
586          printf("      Zero-length file.\n");
587          return;
588       }
589    
590       prev_c = ' ';
591       char_no = 0;
592       line_no = 1;
593       col_no  = 1;
594       in_c    = in_i & 0xff;
595       in_uc   = in_i & 0xff;
596    
597       do
598       {
599          //Illegal characters always get flagged.
600          if (is_illegal_non_eol_character(in_c))
601          {
602             emit_file_pos_3tuple(line_no, col_no, char_no);
603             printf("         Illegal character: 0x%02x.\n", ((unsigned)in_uc));
604          }
605    
606          //printf("Character: %02x  State: %u\n", in_c, (unsigned)state);
607    
608          //Run through the state machine, which would look for bad EOL sequences.
609          switch (state)
610          {
611          case PST_LINE:
612             //Processing non-EOL characters.
613             if (is_lf(in_c))
614             {
615                if ((char_no != 0) && (prev_c == ' '))
616                {
617                   emit_file_pos_3tuple(line_no, col_no, char_no);
618                   printf("         Line contains trailing whitespace.\n");
619                }
620    
621                //Line feeds not allowed without preceding carriage return.
622                emit_file_pos_3tuple(line_no, col_no, char_no);
623                printf("         Out of sequence line feed character (0x0a).\n");
624                line_no++;
625                col_no = 1;
626                state = PST_LF_FOUND;
627             }
628             else if (is_cr(in_c))
629             {
630                if ((char_no != 0) && (prev_c == ' '))
631                {
632                   emit_file_pos_3tuple(line_no, col_no, char_no);
633                   printf("         Line contains trailing whitespace.\n");
634                }
635    
636                //Legal
637                state = PST_CR_FOUND;
638             }
639             else
640             {
641                //Ordinary character.
642                col_no++;
643             }
644             break;
645          case PST_CR_FOUND:
646             if (is_lf(in_c))
647             {
648                //Legal
649                line_no++;
650                col_no = 1;
651                state = PST_LF_FOUND;
652             }
653             else if (is_cr(in_c))
654             {
655                //Back-to-back carriage returns not allowed.
656                emit_file_pos_3tuple(line_no, col_no, char_no);
657                printf("         Out of sequence carriage return character (0x0D).\n");
658                col_no++;
659             }
660             else
661             {
662                //Ordinary character.  Illegal, because LF must follow CR.
663                emit_file_pos_3tuple(line_no, col_no, char_no);
664                printf("         Carriage return followed by 0x%02x rather than LF.\n", (unsigned)in_uc);
665                col_no++;
666             }
667             break;
668          case PST_LF_FOUND:
669             if (is_lf(in_c))
670             {
671                //Illegal.  Back-to-back line feeds not allowed.
672                emit_file_pos_3tuple(line_no, col_no, char_no);
673                printf("         Out of sequence line feed character (0x0A).\n");
674                line_no++;
675                col_no = 1;
676             }
677             else if (is_cr(in_c))
678             {
679                //Legal.  Blank lines are fine.
680                col_no++;
681                state = PST_CR_FOUND;
682             }
683             else
684             {
685                //Ordinary character.  Legal.
686                col_no++;
687                state = PST_LINE;
688             }
689             break;
690          default:
691             USERASSERT_assert(0, __FILE__, __LINE__);
692             break;
693          }
694    
695          in_i = fgetc(f);
696          prev_c = in_c;
697          in_c = in_i & 0xff;
698          in_uc = in_i & 0xff;
699          char_no++;
700          if (in_i == EOF)
701          {
702             if (state != PST_LF_FOUND)
703             {
704                emit_file_pos_3tuple(line_no, col_no, char_no-1);
705                printf("         Final line of file does not have CR/LF sequence.\n");
706             }
707             if ((state == PST_LINE) && (prev_c == ' '))
708             {
709                emit_file_pos_3tuple(line_no, col_no, char_no - 1);
710                printf("         Final line contains trailing whitespace.\n");
711             }
712    
713             exit_flag = 1;
714          }
715       } while (!exit_flag);
716    }
717    
718    void process_file_by_name(const char *s)
719    {
720       FILE *f;
721    
722       printf("   %s\n", s);
723    
724       f = fopen(s, "rb");
725    
726       if (!f)
727       {
728          printf("      fopen() failed.\n");
729       }
730       else
731       {
732          process_opened_handle(f);
733    
734          if (fclose(f))
735          {
736             printf("      fclose() failed.\n");
737          }
738       }
739    }
740    
741    void process_filename_or_wildcard(const char *fname_or_wildcard)
742    {
743       HANDLE hFind;
744       WIN32_FIND_DATA FindFileData;
745    
746       //Incoming pointer is worthy of an assertion.  The OS should not every deliver
747       //a NULL pointer or empty string to us.
748       USERASSERT_assert(fname_or_wildcard != NULL, __FILE__, __LINE__);
749       USERASSERT_assert(strlen(fname_or_wildcard) > 0, __FILE__, __LINE__);
750    
751       printf("%s\n", fname_or_wildcard);
752    
753       if (STRING_is_longer_than_maxpath(fname_or_wildcard))
754       {
755          printf("   Specified filename or wildcard too long--cannot process.\n");
756       }
757       else if (STRING_contains_terminating_backslash(fname_or_wildcard))
758       {
759          printf("   Specified filename or wildcard contains terminating \"\\\"--cannot process.\n");
760       }
761       else if (STRING_contains_wildcard(fname_or_wildcard))
762       {
763          hFind = FindFirstFile((TCHAR *)fname_or_wildcard, &FindFileData);
764    
765          if (hFind == INVALID_HANDLE_VALUE)
766          {
767             printf("   Wildcard does not match existing files or is invalid.\n");
768          }
769          else
770          {
771             char path_drive[_MAX_PATH + 5];
772             char path_dir[_MAX_PATH + 5];
773             char path_fname[_MAX_PATH + 5];
774             char path_ext[_MAX_PATH + 5];
775             char path_full[_MAX_PATH + 5];
776    
777             if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
778             {
779                _splitpath(fname_or_wildcard, path_drive, path_dir, path_fname, path_ext);
780    
781                strcpy(path_full, path_drive);
782                strcat(path_full, path_dir);
783                strcat(path_full, FindFileData.cFileName);
784    
785                process_file_by_name(path_full);
786             }
787    
788             while (FindNextFile(hFind, &FindFileData) != 0)
789             {
790                if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
791                {
792                   _splitpath(fname_or_wildcard, path_drive, path_dir, path_fname, path_ext);
793    
794                   strcpy(path_full, path_drive);
795                   strcat(path_full, path_dir);
796                   strcat(path_full, FindFileData.cFileName);
797    
798                   process_file_by_name(path_full);
799                }
800             }
801          }
802    
803          if (hFind != INVALID_HANDLE_VALUE)
804          {
805             FindClose(hFind);
806          }
807       }
808       else
809       {
810          process_file_by_name(fname_or_wildcard);
811       }
812    }
813    
814    void emit_no_par_documentation(void)
815    {
816       size_t i;
817    
818       FCMIOF_stream_hline(stdout);
819       for (i = 0; i < (sizeof(prog_desc_text) / sizeof(prog_desc_text[0])); i++)
820          printf("%s\n", prog_desc_text[i]);
821       FCMIOF_stream_hline(stdout);
822       for (i = 0; i < (sizeof(license_preamble) / sizeof(license_preamble[0])); i++)
823          printf("%s\n", license_preamble[i]);
824       FCMIOF_stream_hline(stdout);
825       for (i = 0; i < (sizeof(license_text) / sizeof(license_text[0])); i++)
826          printf("%s\n", license_text[i]);
827       FCMIOF_stream_hline(stdout);
828       printf("Program built on %s at %s.\n", __DATE__, __TIME__);
829       i = 0;
830       while (STRING_vcinfo(i))
831       {
832          printf("%s\n", STRING_vcinfo(i));
833          i++;
834       }
835       FCMIOF_stream_hline(stdout);
836       for (i = 0; i < (sizeof(prog_help_text) / sizeof(prog_help_text[0])); i++)
837          printf("%s\n", prog_help_text[i]);
838       FCMIOF_stream_hline(stdout);
839    }
840    
841    void emit_execution_preamble(void)
842    {
843       FCMIOF_stream_hline(stdout);
844       printf("Use \"ifsfscan\" with no parameters to obtain license and help information.\n");
845       FCMIOF_stream_hline(stdout);
846    }
847    
848  int c_main(int argc, char **argv)  int c_main(int argc, char **argv)
849  {  {
850       int i;
851    
852     if (argc <= 1)     if (argc <= 1)
853     {     {
854        //This is most likely someone trying to figure out what the program is or does.        //This is  most likely someone trying to figure out what the program is or does.
855        //Treat this the same as a request for help.        //Spit everything.
856          emit_no_par_documentation();
857       }
858       else
859       {
860          emit_execution_preamble();
861    
862          //Every argument beyond the program name has to be either a file name or
863          //wildcard.  Just process them in order.
864          for (i = 1; i < argc; i++)
865             process_filename_or_wildcard(argv[i]);
866    
867          FCMIOF_stream_hline(stdout);
868     }     }
869    
870     return 0;     return 0;

Legend:
Removed from v.164  
changed lines
  Added in v.199

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25