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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 202 - (hide annotations) (download)
Sun Jul 15 17:17:37 2018 UTC (5 years, 8 months ago) by dashley
Original Path: projs/dtats/trunk/projs/2018/20180112_ifsfscan/c_main.c
File MIME type: text/plain
File size: 23196 byte(s)
Correct source file tab and whitespace anomalies.
1 dashley 150 //$Header$
2 dashley 197 //{f0d952cc-7499-4d5c-9f46-d0b509c5701c}
3 dashley 150 //-------------------------------------------------------------------------------------------------
4 dashley 193 //Copyright (c) 2018, David T. Ashley
5     //
6     //This file is part of "ifsfscan", a program for identifying gross formatting anomalies in source
7     //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 dashley 150 //reproduced below.
11 dashley 193 //
12 dashley 150 //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
14     //Software without restriction, including without limitation the rights to use,
15     //copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the
16     //Software, and to permit persons to whom the Software is furnished to do so,
17     //subject to the following conditions :
18     //
19     //The above copyright notice and this permission notice shall be included in all
20     //copies or substantial portions of the Software.
21     //
22     //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23     //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 dashley 193 //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 dashley 150 //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,
27     //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28     //SOFTWARE.
29     //-------------------------------------------------------------------------------------------------
30     #include <stdio.h>
31 dashley 151 #include <stdlib.h>
32 dashley 193 #include <string.h>
33 dashley 197 #include <tchar.h>
34 dashley 193 #include <time.h>
35 dashley 197 #include <windows.h>
36 dashley 150
37 dashley 193 #define FCMIOF_HORIZONTAL_BAR_SEP_CHAR ('-')
38     #define FCMIOF_LINE_LEN (78)
39    
40     //The last column allowed for a characters below is Column 82 (or it will be
41     //less than aesthetic).
42     const char * const license_preamble[] =
43 dashley 151 {
44 dashley 193 "ifsfscan, (c) 2018 David T. Ashley (dashley@gmail.com)",
45     "This program's source files, executable files, and all other related files",
46     "(such as Visual Studio project files) are licensed under \"The MIT License\",",
47     "reproduced below."
48     };
49    
50     const char * const license_text[] =
51     {
52 dashley 202 "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",
54     "in the Software without restriction, including without limitation the rights",
55     "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 dashley 151 };
70    
71 dashley 193 const char * const prog_desc_text[] =
72 dashley 151 {
73 dashley 202 "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 dashley 193 "errors detected are non-ASCII characters, tab characters, abnormal",
76     "end-of-line characters, and trailing whitespace on lines.",
77 dashley 151 };
78    
79 dashley 193 const char * const prog_help_text[] =
80 dashley 151 {
81 dashley 202 "Usage: ifsfscan [filename_or_wildcard [filename_or_wildcard [...]]]",
82     "",
83     "Notes:",
84 dashley 193 " (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 dashley 202 " (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 dashley 193 " (5) : This program accepts only the ASCII character set (it will not",
92     " process UTF-8 or any other encodings).",
93 dashley 151 };
94    
95     //--------------------------------------------------------------------------------
96     // T E R M I N A T I O N F U N C T I O N S
97     //--------------------------------------------------------------------------------
98 dashley 193 void CCMFATAL_fatal(const char *desc, const char *file, size_t line)
99 dashley 151 {
100 dashley 193 printf("\n");
101 dashley 202 printf("Fatal error. Must terminate execution.\n");
102     printf("File: %s, Line: %zu.\n", file, line);
103     printf("Error description: %s\n", desc);
104     exit(4); //Error code 4 for error termination.
105 dashley 151 }
106    
107     //--------------------------------------------------------------------------------
108     // A S S E R T I O N F U N C T I O N S
109     //--------------------------------------------------------------------------------
110 dashley 193 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 dashley 151
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
124     //--------------------------------------------------------------------------------
125     //These functions form a layer over the standard library so that conditions of
126     //concern can be more easily trapped.
127     //--------------------------------------------------------------------------------
128     void *CCMALLOC_malloc(size_t size)
129     {
130 dashley 202 void *rv;
131 dashley 151
132 dashley 202 rv = malloc(size);
133 dashley 151
134 dashley 202 if (!rv)
135     {
136     CCMFATAL_fatal("NULL pointer from malloc()--probable out of memory.",
137     __FILE__,
138     __LINE__);
139     }
140 dashley 151
141 dashley 193 memset(rv, 0, size);
142    
143 dashley 202 return(rv);
144 dashley 151 }
145    
146     void *CCMALLOC_calloc(size_t num, size_t size)
147     {
148 dashley 202 void *rv;
149 dashley 151
150 dashley 202 rv = calloc(num, size);
151 dashley 151
152 dashley 202 if (!rv)
153     {
154     CCMFATAL_fatal("NULL pointer from calloc()--probable out of memory.",
155     __FILE__,
156     __LINE__);
157     }
158 dashley 151
159 dashley 193 memset(rv, 0, size);
160    
161 dashley 202 return(rv);
162 dashley 151 }
163    
164     void *CCMALLOC_realloc(void *memblock, size_t size)
165     {
166 dashley 202 void *rv;
167 dashley 151
168 dashley 202 rv = realloc(memblock, size);
169 dashley 151
170 dashley 202 if ((!rv) && (size))
171     {
172     CCMFATAL_fatal("NULL pointer from realloc()--probable out of memory.",
173     __FILE__,
174     __LINE__);
175     }
176 dashley 151
177 dashley 202 return(rv);
178 dashley 151 }
179    
180     void CCMALLOC_free(void *memblock)
181     {
182 dashley 202 free(memblock);
183 dashley 151 }
184    
185 dashley 193 //--------------------------------------------------------------------------------
186     // C H A R A C T E R F U N C T I O N S
187     //--------------------------------------------------------------------------------
188 dashley 151 int CHARFUNC_digit_to_val(char digit)
189     {
190 dashley 202 switch (digit)
191     {
192     case '0': return(0);
193     break;
194     case '1': return(1);
195     break;
196     case '2': return(2);
197     break;
198     case '3': return(3);
199     break;
200     case '4': return(4);
201     break;
202     case '5': return(5);
203     break;
204     case '6': return(6);
205     break;
206     case '7': return(7);
207     break;
208     case '8': return(8);
209     break;
210     case '9': return(9);
211     break;
212     default: return(-1);
213     break;
214     }
215 dashley 151 }
216    
217     char CHARFUNC_nibble_to_lc_hex_digit(int nibble)
218     {
219 dashley 202 switch (nibble & 0x0F)
220     {
221     case 0:
222     return('0');
223     break;
224     case 1:
225     return('1');
226     break;
227     case 2:
228     return('2');
229     break;
230     case 3:
231     return('3');
232     break;
233     case 4:
234     return('4');
235     break;
236     case 5:
237     return('5');
238     break;
239     case 6:
240     return('6');
241     break;
242     case 7:
243     return('7');
244     break;
245     case 8:
246     return('8');
247     break;
248     case 9:
249     return('9');
250     break;
251     case 10:
252     return('a');
253     break;
254     case 11:
255     return('b');
256     break;
257     case 12:
258     return('c');
259     break;
260     case 13:
261     return('d');
262     break;
263     case 14:
264     return('e');
265     break;
266     case 15:
267     return('f');
268     break;
269     default:
270 dashley 193 USERASSERT_assert(0, __FILE__, __LINE__);
271 dashley 202 return('?');
272     break;
273     }
274 dashley 151 }
275    
276     void CHARFUNC_int_to_lc_hex_rev(int arg, char *s)
277     {
278 dashley 202 int i;
279 dashley 151
280 dashley 193 USERASSERT_assert(s != NULL, __FILE__, __LINE__);
281 dashley 151
282 dashley 193 for (i = 0; i<8; i++)
283 dashley 202 {
284     s[i] = CHARFUNC_nibble_to_lc_hex_digit(arg);
285     arg >>= 4;
286     }
287 dashley 151 }
288    
289 dashley 193 //--------------------------------------------------------------------------------
290     // 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 dashley 151
302 dashley 193 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 dashley 151
312 dashley 193 int STRING_contains_terminating_backslash(const char *s)
313     {
314     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 dashley 197 "$HeadURL$",
341 dashley 195 "$Date$",
342 dashley 193 "$Revision$",
343 dashley 197 "$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 dashley 193 };
348    
349 dashley 197 if (which < (sizeof(vcinfo) / sizeof(vcinfo[0])))
350     return(vcinfo[which]);
351     else
352     return(NULL);
353 dashley 193 }
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 dashley 151 int FCMIOF_get_line_len(void)
359     {
360 dashley 202 return(FCMIOF_LINE_LEN);
361 dashley 151 }
362    
363     void FCMIOF_stream_repchar(FILE *s, char c, unsigned n)
364     {
365 dashley 193 USERASSERT_assert(s != NULL, __FILE__, __LINE__);
366 dashley 151
367 dashley 202 while (n--)
368     fprintf(s, "%c", c);
369 dashley 151 }
370    
371     void FCMIOF_repchar(char c, unsigned n)
372     {
373 dashley 202 while (n--)
374     printf("%c", c);
375 dashley 151 }
376    
377     void FCMIOF_hline(void)
378     {
379 dashley 202 FCMIOF_repchar(FCMIOF_HORIZONTAL_BAR_SEP_CHAR, FCMIOF_LINE_LEN);
380     printf("\n");
381 dashley 151 }
382    
383     void FCMIOF_stream_hline(FILE *s)
384     {
385 dashley 193 USERASSERT_assert(s != NULL, __FILE__, __LINE__);
386 dashley 151
387 dashley 202 FCMIOF_stream_repchar(s, FCMIOF_HORIZONTAL_BAR_SEP_CHAR, FCMIOF_LINE_LEN);
388     fprintf(s, "\n");
389 dashley 151 }
390    
391     void FCMIOF_stream_bannerheading(FILE *f,
392 dashley 202 char *s,
393     int n_extra_lines)
394 dashley 151 {
395 dashley 202 const int lr_padding = 3;
396     /* The number of spaces on each side of what is printed.
397     */
398     int i;
399     /* General iteration variable.
400     */
401 dashley 151
402 dashley 202 int n_asterisks;
403     int input_arg_len;
404     int n_left_spaces;
405     int n_right_spaces;
406 dashley 151
407 dashley 202 /* Check the file pointer, string pointer, and other par.
408     */
409 dashley 193 USERASSERT_assert(f != NULL, __FILE__, __LINE__);
410     USERASSERT_assert(s != NULL, __FILE__, __LINE__);
411     USERASSERT_assert(n_extra_lines >= 0, __FILE__, __LINE__);
412 dashley 151
413 dashley 202 /* Print the right number of solid lines of asterisks to the
414     ** standard output.
415     */
416     for (i = 0; i<n_extra_lines; i++)
417     {
418     FCMIOF_stream_repchar(f, '*', FCMIOF_LINE_LEN);
419     fprintf(f, "\n");
420     }
421 dashley 151
422 dashley 202 /* Figure out how many asterisks to print on each side of the
423     ** argument, and how many spaces. We also need to figure out
424     ** how many characters of the input argument to print--if there
425     ** are too many characters, we need to truncate.
426     */
427     input_arg_len = strlen(s);
428     if (input_arg_len > (FCMIOF_LINE_LEN - 2 * lr_padding - 2))
429     input_arg_len = FCMIOF_LINE_LEN - 2 * lr_padding - 2;
430 dashley 151
431 dashley 202 n_asterisks = (FCMIOF_LINE_LEN - 2 * lr_padding - input_arg_len) / 2;
432 dashley 151
433 dashley 202 n_left_spaces = lr_padding;
434 dashley 151
435 dashley 202 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 dashley 151
445 dashley 202 /* 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 dashley 151
454 dashley 202 /* 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 dashley 151 }
463    
464     void FCMIOF_bannerheading(char *s, int n_extra_lines)
465     {
466 dashley 193 USERASSERT_assert(s != NULL, __FILE__, __LINE__);
467     USERASSERT_assert(n_extra_lines >= 0, __FILE__, __LINE__);
468 dashley 151
469 dashley 202 FCMIOF_stream_bannerheading(stdout, s, n_extra_lines);
470 dashley 151 }
471    
472     void FCMIOF_time_stream(FILE *s, time_t ltime)
473     {
474 dashley 202 char *p;
475 dashley 151
476 dashley 193 USERASSERT_assert(s != NULL, __FILE__, __LINE__);
477 dashley 151
478 dashley 202 time(&ltime);
479 dashley 151
480 dashley 202 p = ctime(&ltime);
481 dashley 151
482 dashley 202 if (p)
483     {
484     int i;
485 dashley 151
486 dashley 202 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 dashley 151 }
500    
501 dashley 197 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 dashley 199 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 dashley 197 }
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 dashley 202
579 dashley 197 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 dashley 199 in_c = in_i & 0xff;
593     in_uc = in_i & 0xff;
594 dashley 197
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 dashley 199 //printf("Character: %02x State: %u\n", in_c, (unsigned)state);
605    
606 dashley 197 //Run through the state machine, which would look for bad EOL sequences.
607     switch (state)
608     {
609     case PST_LINE:
610 dashley 199 //Processing non-EOL characters.
611 dashley 197 if (is_lf(in_c))
612     {
613 dashley 199 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 dashley 197 //Line feeds not allowed without preceding carriage return.
620     emit_file_pos_3tuple(line_no, col_no, char_no);
621 dashley 199 printf(" Out of sequence line feed character (0x0a).\n");
622 dashley 197 line_no++;
623     col_no = 1;
624     state = PST_LF_FOUND;
625     }
626     else if (is_cr(in_c))
627     {
628 dashley 199 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 dashley 197 //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 dashley 199 printf(" Out of sequence carriage return character (0x0D).\n");
656 dashley 197 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 dashley 199 state = PST_CR_FOUND;
680 dashley 197 }
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 dashley 199 prev_c = in_c;
695     in_c = in_i & 0xff;
696     in_uc = in_i & 0xff;
697 dashley 197 char_no++;
698     if (in_i == EOF)
699 dashley 199 {
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 dashley 197 exit_flag = 1;
712 dashley 199 }
713 dashley 197 } while (!exit_flag);
714     }
715    
716     void process_file_by_name(const char *s)
717     {
718     FILE *f;
719    
720     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 dashley 193 void process_filename_or_wildcard(const char *fname_or_wildcard)
740     {
741 dashley 197 HANDLE hFind;
742     WIN32_FIND_DATA FindFileData;
743    
744 dashley 193 //Incoming pointer is worthy of an assertion. The OS should not every deliver
745     //a NULL pointer or empty string to us.
746 dashley 197 USERASSERT_assert(fname_or_wildcard != NULL, __FILE__, __LINE__);
747 dashley 193 USERASSERT_assert(strlen(fname_or_wildcard) > 0, __FILE__, __LINE__);
748 dashley 151
749 dashley 197 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 dashley 193 }
811    
812     void emit_no_par_documentation(void)
813     {
814     size_t i;
815    
816     FCMIOF_stream_hline(stdout);
817     for (i = 0; i < (sizeof(prog_desc_text) / sizeof(prog_desc_text[0])); i++)
818     printf("%s\n", prog_desc_text[i]);
819     FCMIOF_stream_hline(stdout);
820     for (i = 0; i < (sizeof(license_preamble) / sizeof(license_preamble[0])); i++)
821     printf("%s\n", license_preamble[i]);
822     FCMIOF_stream_hline(stdout);
823     for (i = 0; i < (sizeof(license_text) / sizeof(license_text[0])); i++)
824     printf("%s\n", license_text[i]);
825     FCMIOF_stream_hline(stdout);
826 dashley 197 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 dashley 193 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     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 dashley 150 int c_main(int argc, char **argv)
847     {
848 dashley 193 int i;
849    
850 dashley 150 if (argc <= 1)
851     {
852 dashley 193 //This is most likely someone trying to figure out what the program is or does.
853     //Spit everything.
854     emit_no_par_documentation();
855 dashley 150 }
856 dashley 193 else
857     {
858     emit_execution_preamble();
859 dashley 150
860 dashley 193 //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 dashley 150 return 0;
869 dashley 202 }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision URL Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25