/[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

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

Legend:
Removed from v.151  
changed lines
  Added in v.202

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25