/[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 195 by dashley, Sat Jul 14 21:25:38 2018 UTC 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  //Copyright (c) 2018, David T. Ashley  //Copyright (c) 2018, David T. Ashley
5  //  //
# Line 29  Line 30 
30  #include <stdio.h>  #include <stdio.h>
31  #include <stdlib.h>  #include <stdlib.h>
32  #include <string.h>  #include <string.h>
33    #include <tchar.h>
34  #include <time.h>  #include <time.h>
35    #include <windows.h>
36    
37  #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR    ('-')  #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR    ('-')
38  #define FCMIOF_LINE_LEN                   (78)  #define FCMIOF_LINE_LEN                   (78)
# Line 46  const char * const license_preamble[] = Line 49  const char * const license_preamble[] =
49    
50  const char * const license_text[] =  const char * const license_text[] =
51  {  {
52          "Permission is hereby granted, free of charge, to any person obtaining a copy",     "Permission is hereby granted, free of charge, to any person obtaining a copy",
53          "of this software and associated documentation files(the \"Software\"), to deal",     "of this software and associated documentation files(the \"Software\"), to deal",
54          "in the Software without restriction, including without limitation the rights",     "in the Software without restriction, including without limitation the rights",
55          "to use, copy, modify, merge, publish, distribute, sublicense, and / or sell",     "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",     "copies of the Software, and to permit persons to whom the Software is",
57          "furnished to do so, subject to the following conditions:",     "furnished to do so, subject to the following conditions:",
58          "",     "",
59          "The above copyright notice and this permission notice shall be included in",     "The above copyright notice and this permission notice shall be included in",
60          "all copies or substantial portions of the Software.",     "all copies or substantial portions of the Software.",
61          "",     "",
62          "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",
63          "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",     "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
64          "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE",     "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",     "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,",     "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",     "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
68          "SOFTWARE."     "SOFTWARE."
69  };  };
70    
71  const char * const prog_desc_text[] =  const char * const prog_desc_text[] =
72  {  {
73          "ifsfscan (mnemonic: Ill-Formed Source File SCAN) is a program for detecting",     "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",     "gross formatting errors in source files (Windows/ASCII text files only).  The",
75     "errors detected are non-ASCII characters, tab characters, abnormal",     "errors detected are non-ASCII characters, tab characters, abnormal",
76     "end-of-line characters, and trailing whitespace on lines.",     "end-of-line characters, and trailing whitespace on lines.",
77  };  };
78    
79  const char * const prog_help_text[] =  const char * const prog_help_text[] =
80  {  {
81          "Usage:  ifsfscan [filename_or_wildcard [filename_or_wildcard [...]]]",     "Usage:  ifsfscan [filename_or_wildcard [filename_or_wildcard [...]]]",
82          "",     "",
83          "Notes:",     "Notes:",
84     "   (1) : Wildcards (\"*\", \"?\") are processed by Windows, so Windows is",     "   (1) : Wildcards (\"*\", \"?\") are processed by Windows, so Windows is",
85     "         the arbiter of which wildcards are accepted and how they expand.",     "         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",     "   (2) : This program never writes to a file, so it cannot destroy data",
87          "         (except, possibly, by stdout output redirected to a file).",     "         (except, possibly, by stdout output redirected to a file).",
88          "   (3) : This program accepts no options (like \"-help\" or \"-verbose\").",     "   (3) : This program accepts no options (like \"-help\" or \"-verbose\").",
89          "   (4) : This program accepts only Windows line endings (13-10).",     "   (4) : This program accepts only Windows line endings (13-10).",
90          "         This program is incompatible with *nix and *nix files.",     "         This program is incompatible with *nix and *nix files.",
91     "   (5) : This program accepts only the ASCII character set (it will not",     "   (5) : This program accepts only the ASCII character set (it will not",
92     "         process UTF-8 or any other encodings).",     "         process UTF-8 or any other encodings).",
93  };  };
# Line 95  const char * const prog_help_text[] = Line 98  const char * const prog_help_text[] =
98  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("\n");     printf("\n");
101          printf("Fatal error.  Must terminate execution.\n");     printf("Fatal error.  Must terminate execution.\n");
102          printf("File: %s, Line: %zu.\n", file, line);     printf("File: %s, Line: %zu.\n", file, line);
103          printf("Error description: %s\n", desc);     printf("Error description: %s\n", desc);
104          exit(4);  //Error code 4 for error termination.     exit(4);  //Error code 4 for error termination.
105  }  }
106    
107  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
# Line 124  void USERASSERT_assert(int assertion, co Line 127  void USERASSERT_assert(int assertion, co
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);     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     memset(rv, 0, size);     memset(rv, 0, size);
160    
161          return(rv);     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  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
# Line 185  void CCMALLOC_free(void *memblock) Line 187  void CCMALLOC_free(void *memblock)
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        USERASSERT_assert(0, __FILE__, __LINE__);        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     USERASSERT_assert(s != NULL, __FILE__, __LINE__);     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  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
# Line 335  const char *STRING_vcinfo(size_t which) Line 337  const char *STRING_vcinfo(size_t which)
337  {  {
338     static const char * const vcinfo[] =     static const char * const vcinfo[] =
339     {     {
       "$Author$",  
       "$Date$",  
       "$Header$",  
340        "$HeadURL$",        "$HeadURL$",
341        "$ID$",        "$Date$",
342        "$Revision$",        "$Revision$",
343        "$URL$",        "$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  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
# Line 351  const char *STRING_vcinfo(size_t which) Line 357  const char *STRING_vcinfo(size_t which)
357  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
358  int FCMIOF_get_line_len(void)  int FCMIOF_get_line_len(void)
359  {  {
360          return(FCMIOF_LINE_LEN);     return(FCMIOF_LINE_LEN);
361  }  }
362    
363  void FCMIOF_stream_repchar(FILE *s, char c, unsigned n)  void FCMIOF_stream_repchar(FILE *s, char c, unsigned n)
364  {  {
365     USERASSERT_assert(s != NULL, __FILE__, __LINE__);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
366    
367          while (n--)     while (n--)
368                  fprintf(s, "%c", c);        fprintf(s, "%c", c);
369  }  }
370    
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    
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    
383  void FCMIOF_stream_hline(FILE *s)  void FCMIOF_stream_hline(FILE *s)
384  {  {
385     USERASSERT_assert(s != NULL, __FILE__, __LINE__);     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    
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          */     */
   
         int n_asterisks;  
         int input_arg_len;  
         int n_left_spaces;  
         int n_right_spaces;  
401    
402          /* Check the file pointer, string pointer, and other par.     int n_asterisks;
403          */     int input_arg_len;
404       int n_left_spaces;
405       int n_right_spaces;
406    
407       /* Check the file pointer, string pointer, and other par.
408       */
409     USERASSERT_assert(f != NULL, __FILE__, __LINE__);     USERASSERT_assert(f != NULL, __FILE__, __LINE__);
410     USERASSERT_assert(s != NULL, __FILE__, __LINE__);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
411     USERASSERT_assert(n_extra_lines >= 0, __FILE__, __LINE__);     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;
432    
433          n_left_spaces = lr_padding;     n_left_spaces = lr_padding;
434    
435          if ((FCMIOF_LINE_LEN - 2 * lr_padding - input_arg_len) % 2)     if ((FCMIOF_LINE_LEN - 2 * lr_padding - input_arg_len) % 2)
436          {     {
437                  /* Odd, need to pad the right by one. */        /* Odd, need to pad the right by one. */
438                  n_right_spaces = lr_padding + 1;        n_right_spaces = lr_padding + 1;
439          }     }
440          else     else
441          {     {
442                  n_right_spaces = lr_padding;        n_right_spaces = lr_padding;
443          }     }
444    
445          /* Print the text. */     /* Print the text. */
446          FCMIOF_stream_repchar(f, '*', n_asterisks);     FCMIOF_stream_repchar(f, '*', n_asterisks);
447          FCMIOF_stream_repchar(f, ' ', n_left_spaces);     FCMIOF_stream_repchar(f, ' ', n_left_spaces);
448          for (i = 0; i<input_arg_len; i++)     for (i = 0; i<input_arg_len; i++)
449                  fprintf(f, "%c", s[i]);        fprintf(f, "%c", s[i]);
450          FCMIOF_stream_repchar(f, ' ', n_right_spaces);     FCMIOF_stream_repchar(f, ' ', n_right_spaces);
451          FCMIOF_stream_repchar(f, '*', n_asterisks);     FCMIOF_stream_repchar(f, '*', n_asterisks);
452          fprintf(f, "\n");     fprintf(f, "\n");
453    
454          /* Print the right number of solid lines of asterisks to the     /* Print the right number of solid lines of asterisks to the
455          ** standard output.     ** standard output.
456          */     */
457          for (i = 0; i<n_extra_lines; i++)     for (i = 0; i<n_extra_lines; i++)
458          {     {
459                  FCMIOF_stream_repchar(f, '*', FCMIOF_LINE_LEN);        FCMIOF_stream_repchar(f, '*', FCMIOF_LINE_LEN);
460                  fprintf(f, "\n");        fprintf(f, "\n");
461          }     }
462  }  }
463    
464  void FCMIOF_bannerheading(char *s, int n_extra_lines)  void FCMIOF_bannerheading(char *s, int n_extra_lines)
# Line 460  void FCMIOF_bannerheading(char *s, int n Line 466  void FCMIOF_bannerheading(char *s, int n
466     USERASSERT_assert(s != NULL, __FILE__, __LINE__);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
467     USERASSERT_assert(n_extra_lines >= 0, __FILE__, __LINE__);     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__);     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
477    
478          time(&ltime);     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          p = ctime(&ltime);     printf("   %s\n", s);
721    
722          if (p)     f = fopen(s, "rb");
723          {  
724                  int i;     if (!f)
725       {
726                  for (i = 11; i<19; i++)        printf("      fopen() failed.\n");
727                          fprintf(s, "%c", p[i]);     }
728                  fprintf(s, " ");     else
729                  for (i = 0; i<10; i++)     {
730                          fprintf(s, "%c", p[i]);        process_opened_handle(f);
731                  fprintf(s, " ");  
732                  for (i = 20; i<24; i++)        if (fclose(f))
733                          fprintf(s, "%c", p[i]);        {
734          }           printf("      fclose() failed.\n");
735          else        }
736          {     }
                 fprintf(s, "??? ??? ?? ??:??:?? ????");  
         }  
737  }  }
738    
739  void process_filename_or_wildcard(const char *fname_or_wildcard)  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     //Incoming pointer is worthy of an assertion.  The OS should not every deliver
745     //a NULL pointer or empty string to us.     //a NULL pointer or empty string to us.
746     USERASSERT_assert(fname_or_wildcard != NULL,     __FILE__, __LINE__);     USERASSERT_assert(fname_or_wildcard != NULL, __FILE__, __LINE__);
747     USERASSERT_assert(strlen(fname_or_wildcard) > 0, __FILE__, __LINE__);     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          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  void emit_no_par_documentation(void)  void emit_no_par_documentation(void)
# Line 515  void emit_no_par_documentation(void) Line 823  void emit_no_par_documentation(void)
823     for (i = 0; i < (sizeof(license_text) / sizeof(license_text[0])); i++)     for (i = 0; i < (sizeof(license_text) / sizeof(license_text[0])); i++)
824        printf("%s\n", license_text[i]);        printf("%s\n", license_text[i]);
825     FCMIOF_stream_hline(stdout);     FCMIOF_stream_hline(stdout);
826       printf("Program built on %s at %s.\n", __DATE__, __TIME__);
827       i = 0;
828       while (STRING_vcinfo(i))
829       {
830          printf("%s\n", STRING_vcinfo(i));
831          i++;
832       }
833       FCMIOF_stream_hline(stdout);
834     for (i = 0; i < (sizeof(prog_help_text) / sizeof(prog_help_text[0])); i++)     for (i = 0; i < (sizeof(prog_help_text) / sizeof(prog_help_text[0])); i++)
835        printf("%s\n", prog_help_text[i]);        printf("%s\n", prog_help_text[i]);
836     FCMIOF_stream_hline(stdout);     FCMIOF_stream_hline(stdout);
# Line 550  int c_main(int argc, char **argv) Line 866  int c_main(int argc, char **argv)
866     }     }
867    
868     return 0;     return 0;
 }  
869    }

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25