1 /* lwpp.c: A lightweight text preprocessor.
2 * created 1999-Mar-12 16:42 jmk
3 * autodate: 1999-Aug-15 18:46
4 *
5 * by Jim Knoble <http://www.pobox.com/~jmknoble/>
6 * Copyright 1999 Jim Knoble
7 *
8 * Adapted for use with HuskyPnt by Sascha Silbe <Sascha.Silbe@ldknet.org>
9 *
10 * Disclaimer:
11 *
12 * The software is provided "as is", without warranty of any kind,
13 * express or implied, including but not limited to the warranties of
14 * merchantability, fitness for a particular purpose and
15 * noninfringement. In no event shall the author(s) be liable for any
16 * claim, damages or other liability, whether in an action of
17 * contract, tort or otherwise, arising from, out of or in connection
18 * with the software or the use or other dealings in the software.
19 */
20
21 #define VERSION "1.0hp"
22 #define DATE "2000-Apr-22"
23
24 #include <ctype.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #define MAX_LINE_LEN 1024
30
31 #define KEYWORD_NONE 0
32 #define KEYWORD_DEFINE 1
33 #define KEYWORD_UNDEF 2
34 #define KEYWORD_IFDEF 3
35 #define KEYWORD_ELSE 4
36 #define KEYWORD_ENDIF 5
37 #define KEYWORD_IFNDEF 6
38 #define KEYWORD_IFEQ 7
39 #define KEYWORD_IFNEQ 8
40
41 #define STATUS_OK 1
42 #define STATUS_UNKNOWN_KEYWORD 0
43 #define STATUS_DEFINE_ERROR -1
44 #define STATUS_UNDEF_ERROR -2
45 #define STATUS_MISSING_TOKEN -3
46 #define STATUS_MISSING_VALUE -4
47 #define STATUS_ELSE_WITHOUT_IF -5
48 #define STATUS_ENDIF_WITHOUT_IF -6
49 #define STATUS_MISSING_ENDIF -7
50 #define STATUS_STACK_UNDERFLOW -10
51
52 typedef struct KeywordStruct
53 {
54 char *token;
55 int id;
56 char *text;
57 char *help_text;
58 } Keyword;
59
60 static Keyword keyword_table[] =
61 {
62 { "define", KEYWORD_DEFINE, "=",
63 " define <token> [<value>] Define <token> to have value <value>.\n"
64 " If <value> is omitted, defaults to `1'.\n"
65 "\n"
66 },
67 { "undef", KEYWORD_UNDEF, NULL,
68 " undef <token> Undefine <token>.\n"
69 "\n"
70 },
71 { "ifdef", KEYWORD_IFDEF, "defined",
72 " ifdef <token> If <token> is defined, print the following\n"
73 " lines on the output, until the next `else'\n"
74 " or `endif' directive.\n"
75 "\n"
76 },
77 { "else", KEYWORD_ELSE, NULL,
78 " else If the prior `if' directive evaluated to\n"
79 " false, print the following lines on the\n"
80 " output.\n"
81 "\n"
82 },
83 { "endif", KEYWORD_ENDIF, NULL,
84 " endif Conclude the preceding `if ... [else ...]'.\n"
85 "\n"
86 },
87 { "ifndef", KEYWORD_IFNDEF, "!defined",
88 " ifndef <token> If <token> is *not* defined, print the\n"
89 " following lines on the output, until the\n"
90 " next `else' or `endif' directive.\n"
91 "\n"
92 },
93 { "ifeq", KEYWORD_IFEQ, "==",
94 " ifeq <token> <value> If <token> is lexically equal to <value>,\n"
95 " print the following lines on the output,\n"
96 " until the next `else' or `endif' directive.\n"
97 "\n"
98 },
99 { "ifneq", KEYWORD_IFNEQ, "!=",
100 " ifneq <token> <value> If <token> is *not* lexically equal to\n"
101 " <value>, print the following lines on the\n"
102 " output, until the next `else' or `endif'\n"
103 " directive.\n"
104 "\n"
105 },
106 { NULL, KEYWORD_NONE, NULL, NULL }
107 };
108
109 typedef struct FileStateStruct
110 {
111 int in_if;
112 int in_else;
113 int condition;
114 int parent_condition;
115 char *text;
116 } FileState;
117
118 #define STACK_SIZE_INCREMENT 64
119 typedef struct StackStateStruct
120 {
121 FileState *bottom;
122 int size;
123 int count;
124 } StackState;
125
126 #define DEF_PREFIX "@"
127 #define DEF_VALUE "1"
128 static char *prefix = NULL;
129 static int prefix_len = 0;
130
131 char *prog_name = NULL;
132 int verbose = 0;
133
134 char version_info[] = ""
135 "lwpp version " VERSION " (" DATE ")\n"
136 "by Jim Knoble <http://www.pobox.com/~jmknoble/>\n"
137 "Provided as is with no warranty of any kind, etc., etc.\n"
138 ;
139
140 char usage_info[] =
141 "\n"
142 "Usage: %s [-p <text>] [-D<token>[=<val>]] [-U<token>] [-v] [<filename>]\n"
143 "\n"
144 "Preprocess <filename>, sending the result to the standard output.\n"
145 "If <filename> is not specified, read from the standard input.\n"
146 "\n"
147 "Options:\n"
148 " -p<text> Preprocessor directives are prefixed with\n"
149 " --prefix <text> <text>. Defaults to `" DEF_PREFIX "'.\n"
150 "\n"
151 " -D<token>[=<val>] Define <token> to have value <val>. If\n"
152 " --define <token>[=<val>] <val> is omitted, defaults to `" DEF_VALUE "'.\n"
153 "\n"
154 " -U<token> Undefine <token>.\n"
155 " --undef <token>\n"
156 "\n"
157 " -v Be verbose.\n"
158 " --verbose\n"
159 "\n"
160 " -V Show version information.\n"
161 " --version\n"
162 "\n"
163 "Preprocessing Directives:\n"
164 ;
165
166 /**********************************************************************/
out_of_memory(int line_num)167 void out_of_memory(int line_num)
168 {
169 fprintf(stderr, "%s:line %d: Out of memory\n", prog_name, line_num);
170 exit(1);
171 }
172
init_stack(StackState * stack)173 void init_stack(StackState *stack)
174 {
175 stack->bottom = NULL;
176 stack->size = 0;
177 stack->count = 0;
178 }
179
increase_stack_size(StackState * stack)180 void increase_stack_size(StackState *stack)
181 {
182 stack->size += STACK_SIZE_INCREMENT;
183 stack->bottom = realloc(stack->bottom, stack->size * sizeof(FileState));
184 if (NULL == stack->bottom)
185 {
186 out_of_memory(__LINE__);
187 }
188 }
189
init_file_state(FileState * state)190 void init_file_state(FileState *state)
191 {
192 state->in_if = 0;
193 state->in_else = 0;
194 state->condition = 1;
195 state->parent_condition = 1;
196 state->text = NULL;
197 }
198
copy_file_state(FileState * dst,FileState * src)199 void copy_file_state(FileState *dst, FileState *src)
200 {
201 dst->in_if = src->in_if;
202 dst->in_else = src->in_else;
203 dst->condition = src->condition;
204 dst->parent_condition = src->parent_condition;
205 dst->text = src->text;
206 }
207
push_file_state(StackState * stack,FileState * state)208 void push_file_state(StackState *stack, FileState *state)
209 {
210 FileState *top;
211
212 if (stack->count == stack->size)
213 {
214 increase_stack_size(stack);
215 }
216 top = (stack->bottom + stack->count);
217 (stack->count)++;
218 copy_file_state(top, state);
219 }
220
pop_file_state(StackState * stack,FileState * state)221 int pop_file_state(StackState *stack, FileState *state)
222 {
223 int status = STATUS_STACK_UNDERFLOW;
224 FileState *top;
225
226 if (0 < stack->count)
227 {
228 status = STATUS_OK;
229 (stack->count)--;
230 top = (stack->bottom + stack->count);
231 copy_file_state(state, top);
232 }
233 return(status);
234 }
235
find_keyword(char * token)236 Keyword *find_keyword(char *token)
237 {
238 Keyword *kw = keyword_table;
239
240 while (NULL != kw->token)
241 {
242 if (0 == strcmp(token, kw->token))
243 {
244 break;
245 }
246 kw++;
247 }
248 return(kw);
249 }
250
lookup_definition(char * token)251 char *lookup_definition(char *token)
252 {
253 char *value = NULL;
254
255 if (NULL != token)
256 {
257 value = getenv(token);
258 }
259 return(value);
260 }
261
262 #ifndef USE_PUTENV
create_definition(char * token,char * value)263 int create_definition(char *token, char *value)
264 {
265 int status = 0;
266
267 if ((NULL != token) && (0 < strlen(token)) && (NULL != value))
268 {
269 status = (0 == setenv(token, value, 1));
270 }
271 return(status);
272 }
273
remove_definition(char * token)274 int remove_definition(char *token)
275 {
276 unsetenv(token);
277 return(1);
278 }
279 #else /* USE_PUTENV */
create_definition(char * token,char * value)280 int create_definition(char *token, char *value)
281 {
282 int status = 0;
283 char *definition;
284 int n;
285
286 if (NULL != token)
287 {
288 n = strlen(token);
289 if (0 < n)
290 {
291 if (NULL == value)
292 {
293 status = (0 == putenv(token));
294 }
295 else
296 {
297 n += strlen(value);
298 definition = malloc(n + 2);
299 if (NULL == definition)
300 {
301 out_of_memory(__LINE__);
302 }
303 strcpy(definition, token);
304 strcat(definition, "=");
305 if (NULL != value)
306 {
307 strcat(definition, value);
308 }
309 status = (0 == putenv(definition));
310 free(definition);
311 }
312 }
313 }
314 return(status);
315 }
316
remove_definition(char * token)317 int remove_definition(char *token)
318 {
319 int status = create_definition(token, NULL);
320 return(status);
321 }
322 #endif /* !USE_PUTENV */
323
is_defined(char * token)324 int is_defined(char *token)
325 {
326 int status = 0;
327 char *value;
328
329 if (NULL != token)
330 {
331 value = getenv(token);
332 return ((value != NULL) && (strlen(value) > 0));
333 }
334 return(status);
335 }
336
is_prefixed_line(char * line)337 int is_prefixed_line(char *line)
338 {
339 int status = 0;
340
341 if (NULL != line)
342 {
343 status = (0 == strncmp(line, prefix, prefix_len));
344 }
345 return(status);
346 }
347
skip_white(char * line)348 char *skip_white(char *line)
349 {
350 char *c = line;
351
352 if (NULL != c)
353 {
354 while (isspace(*c))
355 {
356 c++;
357 }
358 }
359 return(c);
360 }
361
skip_prefix(char * line)362 char *skip_prefix(char *line)
363 {
364 char *new_line = line;
365 int i;
366
367 for (i = 0; i < prefix_len; i++)
368 {
369 if ('\0' == *new_line)
370 {
371 break;
372 }
373 new_line++;
374 }
375 new_line = skip_white(new_line);
376
377 return(new_line);
378 }
379
skip_quoted_string(char ** line,int * n)380 char *skip_quoted_string(char **line, int *n)
381 {
382 char *c = *line;
383 char quote;
384
385 if (NULL != c)
386 {
387 quote = *c;
388 (*line)++;
389 c++;
390 while (('\0' != *c) && (quote != *c))
391 {
392 (*n)++;
393 c++;
394 }
395 }
396 return(c);
397 }
398
extract_next_token(char ** line)399 char *extract_next_token(char **line)
400 {
401 int n = 0;
402 char *c = *line;
403 char *token = NULL;
404
405 if (NULL != c)
406 {
407 if (('"' == *c) || ('\'' == *c))
408 {
409 c = skip_quoted_string(line, &n);
410 }
411 else
412 {
413 while (('\0' != *c) && !isspace(*c))
414 {
415 n++;
416 c++;
417 }
418 }
419 if (0 < n)
420 {
421 token = malloc(n + 1);
422 if (NULL == token)
423 {
424 out_of_memory(__LINE__);
425 }
426 strncpy(token, *line, n);
427 token[n] = '\0';
428 if (('"' == *c) || ('\'' == *c))
429 {
430 c++;
431 }
432 *line = skip_white(c);
433 }
434 }
435 return(token);
436 }
437
print_warning(int status,char * filename,char * keyword,char * token,int line_num)438 void print_warning(int status, char *filename, char *keyword, char *token,
439 int line_num)
440 {
441 char *msg;
442 int need_keyword = 0;
443 int need_token = 0;
444
445 switch (status)
446 {
447 case STATUS_OK:
448 msg = "Oops ... no error. This shouldn't happen.";
449 break;
450 case STATUS_UNKNOWN_KEYWORD:
451 msg = "Unknown keyword";
452 need_token = 1;
453 break;
454 case STATUS_DEFINE_ERROR:
455 msg = "Error defining token";
456 need_token = 1;
457 break;
458 case STATUS_UNDEF_ERROR:
459 msg = "Error undefining token";
460 need_token = 1;
461 break;
462 case STATUS_MISSING_TOKEN:
463 msg = "Missing token for keyword";
464 need_keyword = 1;
465 break;
466 case STATUS_MISSING_VALUE:
467 msg = "Missing comparison value for expression";
468 need_keyword = 1;
469 break;
470 case STATUS_ELSE_WITHOUT_IF:
471 msg = "else without if";
472 break;
473 case STATUS_ENDIF_WITHOUT_IF:
474 msg = "endif without if";
475 break;
476 case STATUS_MISSING_ENDIF:
477 msg = "missing endif";
478 need_keyword = 1;
479 break;
480 case STATUS_STACK_UNDERFLOW:
481 msg = "File state stack underflow";
482 break;
483 default:
484 msg = "Unknown error";
485 break;
486 }
487 if (need_keyword && need_token)
488 {
489 fprintf(stderr, "%s:%d: %s: `%s %s'\n", filename, line_num, msg,
490 keyword, token);
491 }
492 else if (need_keyword)
493 {
494 fprintf(stderr, "%s:%d: %s: `%s'\n", filename, line_num, msg, keyword);
495 }
496 else if (need_token)
497 {
498 fprintf(stderr, "%s:%d: %s: `%s'\n", filename, line_num, msg, token);
499 }
500 else
501 {
502 fprintf(stderr, "%s:%d: %s\n", filename, line_num, msg);
503 }
504 }
505
process_line(char * infilename,FILE * outfile,StackState * stack,FileState * state,char * buf,int line_num)506 int process_line(char *infilename, FILE *outfile,
507 StackState *stack, FileState *state,
508 char *buf, int line_num)
509 {
510 int status = STATUS_OK;
511 char *line = buf;
512 char *keyword = NULL;
513 Keyword *kw = NULL;
514 char *token = NULL;
515 char *value = NULL;
516 char *default_value = DEF_VALUE;
517 char *txt = NULL;
518
519 if (!is_prefixed_line(line))
520 {
521 if ((state->condition) && (state->parent_condition))
522 {
523 fputs(line, outfile);
524 }
525 }
526 else
527 {
528 line = skip_prefix(line);
529 keyword = extract_next_token(&line);
530 kw = find_keyword(keyword);
531 switch (kw->id)
532 {
533 case KEYWORD_DEFINE:
534 token = extract_next_token(&line);
535 value = extract_next_token(&line);
536 if (NULL == value)
537 {
538 status = create_definition(token, default_value);
539 txt = default_value;
540 }
541 else
542 {
543 status = create_definition(token, value);
544 txt = value;
545 }
546 if (verbose)
547 {
548 fprintf(stderr, "%s:%d: define (\"%s\" %s \"%s\")\n",
549 infilename, line_num, token, kw->text, txt);
550 }
551 if (!status)
552 {
553 status = STATUS_DEFINE_ERROR;
554 }
555 break;
556 case KEYWORD_UNDEF:
557 token = extract_next_token(&line);
558 status = remove_definition(token);
559 if (verbose)
560 {
561 fprintf(stderr, "%s:%d: undef (\"%s\")\n",
562 infilename, line_num, token);
563 }
564 if (!status)
565 {
566 status = STATUS_UNDEF_ERROR;
567 }
568 break;
569 case KEYWORD_IFDEF:
570 /* Fall through */
571 case KEYWORD_IFNDEF:
572 token = extract_next_token(&line);
573 if (NULL == token)
574 {
575 status = STATUS_MISSING_TOKEN;
576 }
577 else
578 {
579 int n;
580
581 push_file_state(stack, state);
582 state->in_if = 1;
583 state->in_else = 0;
584 state->parent_condition = state->condition;
585 if (state->parent_condition)
586 {
587 if (KEYWORD_IFDEF == kw->id)
588 {
589 state->condition = is_defined(token);
590 }
591 else
592 {
593 state->condition = !is_defined(token);
594 }
595 }
596 n = strlen(kw->text) + 1 + strlen(token) + 2 + 1;
597 state->text = malloc(n);
598 if (NULL == state->text)
599 {
600 out_of_memory(__LINE__);
601 }
602 sprintf(state->text, "%s \"%s\"", kw->text, token);
603 if (verbose)
604 {
605 fprintf(stderr, "%s:%d: if (%s): %s\n",
606 infilename, line_num, state->text,
607 (state->condition ? "true" : "false"));
608 }
609 }
610 break;
611 case KEYWORD_ELSE:
612 if (!state->in_if)
613 {
614 status = STATUS_ELSE_WITHOUT_IF;
615 }
616 else
617 {
618 state->in_if = 0;
619 state->in_else = 1;
620 state->condition = !(state->condition);
621 if (verbose)
622 {
623 fprintf(stderr, "%s:%d: else (%s): %s\n",
624 infilename, line_num, state->text,
625 (state->condition ? "true" : "false"));
626 }
627 }
628 break;
629 case KEYWORD_ENDIF:
630 if (!(state->in_if) && !(state->in_else))
631 {
632 status = STATUS_ENDIF_WITHOUT_IF;
633 }
634 else
635 {
636 if (verbose)
637 {
638 fprintf(stderr, "%s:%d: endif (%s)\n",
639 infilename, line_num, state->text);
640 }
641 if (NULL != state->text)
642 {
643 free(state->text);
644 }
645 status = pop_file_state(stack, state);
646 }
647 break;
648 case KEYWORD_IFEQ:
649 /* Fall through */
650 case KEYWORD_IFNEQ:
651 token = extract_next_token(&line);
652 if (NULL == token)
653 {
654 status = STATUS_MISSING_TOKEN;
655 }
656 else
657 {
658 value = extract_next_token(&line);
659 if (NULL == value)
660 {
661 status = STATUS_MISSING_VALUE;
662 }
663 else
664 {
665 int n;
666
667 push_file_state(stack, state);
668 state->in_if = 1;
669 state->in_else = 0;
670 state->parent_condition = state->condition;
671 if (state->parent_condition)
672 {
673 char *def = lookup_definition(token);
674 if (KEYWORD_IFEQ == kw->id)
675 {
676 state->condition = ((NULL != def) &&
677 (0 == strcmp(def, value)));
678 }
679 else
680 {
681 state->condition = ((NULL != def) &&
682 (0 != strcmp(def, value)));
683 }
684 }
685 n = strlen(token) + 2 + 1 + strlen(kw->text) + 1 +
686 strlen(value) + 2 + 1;
687 state->text = malloc(n);
688 if (NULL == state->text)
689 {
690 out_of_memory(__LINE__);
691 }
692 sprintf(state->text, "\"%s\" %s \"%s\"",
693 token, kw->text, value);
694 if (verbose)
695 {
696 fprintf(stderr, "%s:%d: if (%s): %s\n",
697 infilename, line_num, state->text,
698 (state->condition ? "true" : "false"));
699 }
700 }
701 }
702 break;
703 default:
704 status = STATUS_UNKNOWN_KEYWORD;
705 break;
706 }
707 if (status < STATUS_OK)
708 {
709 print_warning(status, infilename, keyword, token, line_num);
710 }
711 if (NULL != keyword)
712 {
713 free(keyword);
714 }
715 if (NULL != token)
716 {
717 free(token);
718 }
719 if (NULL != value)
720 {
721 free(value);
722 }
723 }
724 return(status);
725 }
726
process_input_file(char * infilename,char * outfilename)727 int process_input_file(char *infilename, char *outfilename)
728 {
729 int status = 1;
730 FILE *infile = stdin;
731 FILE *outfile = stdout;
732 int using_stdin = 1;
733 int using_stdout = 1;
734 char *munged_infilename = "stdin";
735 char *munged_outfilename = "stdout";
736 char buffer[MAX_LINE_LEN];
737 char *line;
738 int line_num = 0;
739 StackState stack;
740 FileState state;
741
742 if (0 != strcmp(infilename, "-"))
743 {
744 using_stdin = 0;
745 munged_infilename = infilename;
746 infile = fopen(infilename, "r");
747 if (NULL == infile)
748 {
749 perror(infilename);
750 return(0);
751 }
752 }
753 if (0 != strcmp(outfilename, "-"))
754 {
755 using_stdout = 0;
756 munged_outfilename = outfilename;
757 outfile = fopen(outfilename, "w");
758 if (NULL == outfile)
759 {
760 perror(outfilename);
761 if (!using_stdin)
762 {
763 fclose(infile);
764 }
765 return(0);
766 }
767 }
768 if (verbose)
769 {
770 fprintf(stderr, "Processing %s ...\n", munged_infilename);
771 }
772
773 init_stack(&stack);
774 init_file_state(&state);
775 while(NULL != fgets(buffer, sizeof(buffer), infile))
776 {
777 line = buffer;
778 line_num++;
779 status = process_line(munged_infilename, outfile,
780 &stack, &state, line, line_num);
781 }
782 if (stack.count > 0)
783 {
784 print_warning(STATUS_MISSING_ENDIF, munged_infilename, state.text,
785 NULL, line_num);
786 }
787 putc('\n', outfile);
788 if (!using_stdin)
789 {
790 fclose(infile);
791 }
792 if (!using_stdout)
793 {
794 fclose(outfile);
795 }
796 return(status);
797 }
798
usage(void)799 void usage(void)
800 {
801 Keyword *kw;
802
803 fprintf(stderr, usage_info, prog_name);
804 kw = keyword_table;
805 while (NULL != kw->token)
806 {
807 fprintf(stderr, kw->help_text);
808 kw++;
809 }
810 exit(1);
811 }
812
show_version(void)813 void show_version(void)
814 {
815 fprintf(stderr, version_info);
816 }
817
process_args(int argc,char ** argv)818 int process_args(int argc, char **argv)
819 {
820 int i;
821 char *t;
822 char *v;
823
824 for (i = 1; i < argc; i++)
825 {
826 if ('-' != argv[i][0])
827 {
828 break;
829 }
830 else if ((0 == strcmp(argv[i], "-h")) ||
831 (0 == strcmp(argv[i], "--help")))
832 {
833 show_version();
834 usage();
835 }
836 else if ((0 == strncmp(argv[i], "-p", 2)) ||
837 (0 == strcmp(argv[i], "--prefix")))
838 {
839 if (2 <= strlen(argv[i]))
840 {
841 t = (argv[i] + 2);
842 }
843 else if (i >= argc)
844 {
845 break;
846 }
847 else
848 {
849 t = argv[++i];
850 }
851 prefix = t;
852 }
853 else if ((0 == strcmp(argv[i], "-v")) ||
854 (0 == strcmp(argv[i], "--verbose")))
855 {
856 verbose = 1;
857 }
858 else if ((0 == strcmp(argv[i], "-V")) ||
859 (0 == strcmp(argv[i], "--version")))
860 {
861 show_version();
862 exit(1);
863 }
864 else if ((0 == strncmp(argv[i], "-D", 2)) ||
865 (0 == strcmp(argv[i], "--define")))
866 {
867 if (2 <= strlen(argv[i]))
868 {
869 t = (argv[i] + 2);
870 }
871 else if (i >= argc)
872 {
873 break;
874 }
875 else
876 {
877 t = argv[++i];
878 }
879 v = strchr(t, '=');
880 if (NULL == v)
881 {
882 create_definition(t, DEF_VALUE);
883 }
884 else
885 {
886 *(v++) = '\0';
887 create_definition(t, v);
888 }
889 if (verbose)
890 {
891 fprintf(stderr, "Defined token `%s' with value `%s'\n",
892 t, lookup_definition(t));
893 }
894 }
895 else if ((0 == strncmp(argv[i], "-U", 2)) ||
896 (0 == strcmp(argv[i], "--undef")))
897 {
898 if (2 <= strlen(argv[i]))
899 {
900 t = (argv[i] + 2);
901 }
902 else if (i >= argc)
903 {
904 break;
905 }
906 else
907 {
908 t = argv[++i];
909 }
910 remove_definition(t);
911 if (verbose)
912 {
913 fprintf(stderr, "Undefined token `%s'\n", t);
914 }
915 }
916 else if (0 == strcmp(argv[i], "-"))
917 {
918 /* '-' is a filename meaning stdin;
919 * leave it in the list of files to process.
920 */
921 break;
922 }
923 else if (0 == strcmp(argv[i], "--"))
924 {
925 /* End of options. */
926 i++;
927 break;
928 }
929 else
930 {
931 fprintf(stderr, "%s: Unknown option `%s'\n", prog_name, argv[i]);
932 usage();
933 }
934 }
935 return(i);
936 }
937
main(int argc,char ** argv)938 int main(int argc, char **argv)
939 {
940 int i;
941 int status;
942 char *outfilename = "-";
943
944 prog_name = argv[0];
945
946 i = process_args(argc, argv);
947
948 if (NULL == prefix)
949 {
950 prefix = DEF_PREFIX;
951 }
952 prefix_len = strlen(prefix);
953
954 if (i >= argc)
955 {
956 /* No files specified on command line; use stdin. */
957 status = process_input_file("-", outfilename);
958 }
959 else
960 {
961 status = process_input_file(argv[i], outfilename);
962 }
963
964 return(status ? 0 : 1);
965 }
966
967