/[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 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  //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    
38  #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR    ('-')  #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR    ('-')
39  #define FCMIOF_LINE_LEN                   (78)  #define FCMIOF_LINE_LEN                   (78)
# Line 335  const char *STRING_vcinfo(size_t which) Line 339  const char *STRING_vcinfo(size_t which)
339  {  {
340     static const char * const vcinfo[] =     static const char * const vcinfo[] =
341     {     {
       "$Author$",  
       "$Date$",  
       "$Header$",  
342        "$HeadURL$",        "$HeadURL$",
343        "$ID$",        "$Date$",
344        "$Revision$",        "$Revision$",
345        "$URL$",        "$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  //--------------------------------------------------------------------------------  //--------------------------------------------------------------------------------
# Line 492  void FCMIOF_time_stream(FILE *s, time_t Line 500  void FCMIOF_time_stream(FILE *s, time_t
500          }          }
501  }  }
502    
503    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)  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     //Incoming pointer is worthy of an assertion.  The OS should not every deliver
747     //a NULL pointer or empty string to us.     //a NULL pointer or empty string to us.
748     USERASSERT_assert(fname_or_wildcard != NULL,     __FILE__, __LINE__);     USERASSERT_assert(fname_or_wildcard != NULL, __FILE__, __LINE__);
749     USERASSERT_assert(strlen(fname_or_wildcard) > 0, __FILE__, __LINE__);     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)  void emit_no_par_documentation(void)
# Line 515  void emit_no_par_documentation(void) Line 825  void emit_no_par_documentation(void)
825     for (i = 0; i < (sizeof(license_text) / sizeof(license_text[0])); i++)     for (i = 0; i < (sizeof(license_text) / sizeof(license_text[0])); i++)
826        printf("%s\n", license_text[i]);        printf("%s\n", license_text[i]);
827     FCMIOF_stream_hline(stdout);     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++)     for (i = 0; i < (sizeof(prog_help_text) / sizeof(prog_help_text[0])); i++)
837        printf("%s\n", prog_help_text[i]);        printf("%s\n", prog_help_text[i]);
838     FCMIOF_stream_hline(stdout);     FCMIOF_stream_hline(stdout);

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25