1 /* Alexey's C compiler. */
16 unsigned int line
, column
;
20 #define __noreturn __attribute((noreturn))
21 #define __printf(a, b) __attribute__((format(printf, a, b)))
24 #define __printf(a, b)
27 static void warning(struct pos
*pos
, const char *fmt
, ...) __printf(2, 3);
28 static void warning(struct pos
*pos
, const char *fmt
, ...)
32 fprintf(stderr
, "%u:%u: warning: ", pos
->line
, pos
->column
);
34 vfprintf(stderr
, fmt
, args
);
39 static void error_exit(struct pos
*pos
, const char *fmt
, ...) __printf(2, 3) __noreturn
;
40 static void error_exit(struct pos
*pos
, const char *fmt
, ...)
44 fprintf(stderr
, "%u:%u: error: ", pos
->line
, pos
->column
);
46 vfprintf(stderr
, fmt
, args
);
52 static void perror_exit(const char *fmt
, ...) __printf(1, 2) __noreturn
;
53 static void perror_exit(const char *fmt
, ...)
55 int old_errno
= errno
;
58 fputs("acc: ", stderr
);
60 vfprintf(stderr
, fmt
, args
);
68 static void _error_exit(const char *fmt
, ...) __printf(1, 2) __noreturn
;
69 static void _error_exit(const char *fmt
, ...)
73 fputs("acc: error: ", stderr
);
75 vfprintf(stderr
, fmt
, args
);
81 static void *xmalloc(size_t size
)
87 perror_exit("%s: size %zu", __func__
, size
);
91 static void *xmemdup(const void *src
, size_t n
)
100 static ssize_t
_xread(int fd
, void *buf
, size_t count
)
105 rv
= read(fd
, buf
, count
);
106 } while (rv
== -1 && (errno
== EAGAIN
|| errno
== EINTR
));
110 static void xread(int fd
, void *buf
, size_t count
)
115 rv
= _xread(fd
, buf
, count
);
117 perror_exit("read fd %d, buf %p, count %zu", fd
, buf
, count
);
119 _error_exit("fd %d truncated, buf %p, count %zu", fd
, buf
, count
);
121 buf
= (char *)buf
+ rv
;
126 static void fix_newline(char *c
, unsigned int *nr_c
)
132 if (c
[i
] == '\r' && i
+ 1 < *nr_c
&& c
[i
+ 1] == '\n') {
133 memmove(&c
[i
], &c
[i
+ 1], *nr_c
- i
- 1);
135 } else if (c
[i
] == '\r') {
143 static struct pos
*line_column(const char *c
, unsigned int nr_c
)
146 unsigned int line
, column
;
149 if (nr_c
>= 0xffffffff / sizeof(struct pos
))
150 _error_exit("integer overflow nr_c %u", nr_c
);
151 pos
= xmalloc(nr_c
* sizeof(struct pos
));
155 for (i
= 0; i
< nr_c
; i
++) {
157 pos
[i
].column
= column
;
168 static void warn_trigraph(const char *c
, unsigned int nr_c
, struct pos
*pos
)
173 while (i
+ 2 < nr_c
) {
174 if (c
[i
] == '?' && c
[i
+ 1] == '?') {
176 case '=':case ')':case '!':
177 case '(':case '\'':case '>':
178 case '/':case '<':case '-':
179 warning(&pos
[i
], "trigraph sequence ??%c, ignoring", (unsigned char)c
[i
+ 2]);
190 static void delete_backslash_newline(char *c
, unsigned int *nr_c
, struct pos
*pos
)
195 while (i
+ 1 < *nr_c
) {
196 if (c
[i
] == '\\' && c
[i
+ 1] == '\n') {
197 unsigned int nr_to_move
= *nr_c
- i
- 2;
199 memmove(&c
[i
], &c
[i
+ 2], nr_to_move
);
200 memmove(&pos
[i
], &pos
[i
+ 2], nr_to_move
* sizeof(struct pos
));
208 struct pp_token
*next
;
210 PP_TOKEN_IDENTIFIER
= UCHAR_MAX
+ 1,
214 PP_TOKEN_INCLUDE_GLOBAL
, /* #include < */
215 PP_TOKEN_INCLUDE_LOCAL
, /* #include " */
216 PP_TOKEN_DEFINE
, /* #define */
217 PP_TOKEN_IFDEF
, /* #ifdef */
218 PP_TOKEN_IFNDEF
, /* #ifndef */
220 #define _2(c1, c2) (((c1) << 8) | (c2))
221 #define _3(c1, c2, c3) (((c1) << 16)| ((c2) << 8) | (c3))
222 PP_TOKEN_DOTDOTDOT
= _3('.', '.', '.'),
223 PP_TOKEN_DEREFERENCE
= _2('-', '>'),
224 PP_TOKEN_SUB_EQ
= _2('-', '='),
225 PP_TOKEN_DEC
= _2('-', '-'),
226 PP_TOKEN_ADD_EQ
= _2('+', '='),
227 PP_TOKEN_INC
= _2('+', '+'),
228 PP_TOKEN_AND_EQ
= _2('&', '='),
229 PP_TOKEN_AND
= _2('&', '&'),
230 PP_TOKEN_MUL_EQ
= _2('*', '='),
231 PP_TOKEN_NOT_EQ
= _2('!', '='),
232 PP_TOKEN_DIV_EQ
= _2('/', '='),
233 PP_TOKEN_REM_EQ
= _2('%', '='),
234 PP_TOKEN_LSHIFT_EQ
= _3('<', '<', '='),
235 PP_TOKEN_LSHIFT
= _2('<', '<'),
236 PP_TOKEN_LEQ
= _2('<', '='),
237 PP_TOKEN_RSHIFT_EQ
= _3('>', '>', '='),
238 PP_TOKEN_RSHIFT
= _2('>', '>'),
239 PP_TOKEN_GEQ
= _2('>', '='),
240 PP_TOKEN_EQ
= _2('=', '='),
241 PP_TOKEN_XOR_EQ
= _2('^', '='),
242 PP_TOKEN_OR_EQ
= _2('|', '='),
243 PP_TOKEN_OR
= _2('|', '|'),
244 PP_TOKEN_SHARPSHARP
= _2('#', '#'),
248 char *str
; /* string representation, if type is not enough */
252 static struct pp_token
*pp_token_create(enum pp_token_type type
, struct pos
*pos
)
254 struct pp_token
*ppt
;
256 ppt
= xmalloc(sizeof(struct pp_token
));
265 static void pp_token_add(struct pp_token
*ppt
, const char *c
, unsigned int start
, unsigned int end
)
267 ppt
->str
= xmemdup(&c
[start
], end
- start
+ 1);
268 ppt
->str
[end
- start
] = '\0';
271 static void pp_token_free(struct pp_token
*ppt_head
)
273 struct pp_token
*ppt
;
277 struct pp_token
*next
;
287 static void pp_token_print(struct pp_token
*ppt
)
289 printf("%u:%u:\t", ppt
->pos
.line
, ppt
->pos
.column
);
297 case PP_TOKEN_IDENTIFIER
:
298 printf("pp-identifier %s", ppt
->str
);
300 case PP_TOKEN_NUMBER
:
301 printf("pp-number %s", ppt
->str
);
303 case PP_TOKEN_STRING
:
304 printf("pp-string \"%s\"", ppt
->str
);
307 printf("pp-char '%s'", ppt
->str
);
309 case PP_TOKEN_INCLUDE_GLOBAL
:
310 printf("#include <%s>", ppt
->str
);
312 case PP_TOKEN_INCLUDE_LOCAL
:
313 printf("#include \"%s\"", ppt
->str
);
315 case PP_TOKEN_DEFINE
:
316 printf("#define %s", ppt
->str
);
319 printf("#ifdef %s", ppt
->str
);
321 case PP_TOKEN_IFNDEF
:
322 printf("#ifndef %s", ppt
->str
);
324 case PP_TOKEN_DOTDOTDOT
:
325 case PP_TOKEN_LSHIFT_EQ
:
326 case PP_TOKEN_RSHIFT_EQ
:
327 printf("%c%c%c", (ppt
->type
>> 16) & 0xff, (ppt
->type
>> 8) & 0xff, ppt
->type
& 0xff);
329 case PP_TOKEN_DEREFERENCE
:
330 case PP_TOKEN_SUB_EQ
:
332 case PP_TOKEN_ADD_EQ
:
334 case PP_TOKEN_AND_EQ
:
336 case PP_TOKEN_MUL_EQ
:
337 case PP_TOKEN_NOT_EQ
:
338 case PP_TOKEN_DIV_EQ
:
339 case PP_TOKEN_REM_EQ
:
340 case PP_TOKEN_LSHIFT
:
342 case PP_TOKEN_RSHIFT
:
345 case PP_TOKEN_XOR_EQ
:
348 case PP_TOKEN_SHARPSHARP
:
349 printf("%c%c", (ppt
->type
>> 8) & 0xff, ppt
->type
& 0xff);
352 printf("%c", ppt
->type
);
357 static int pp_nondigit(const char c
)
359 return ('a' <= c
&& c
<= 'z') || ('A' <= c
&& c
<= 'Z') || c
== '_';
362 static int pp_octdigit(const char c
)
364 return '0' <= c
&& c
<= '7';
367 static int pp_digit(const char c
)
369 return '0' <= c
&& c
<= '9';
372 static int pp_hexdigit(const char c
)
374 return pp_digit(c
) || ('a' <= c
&& c
<= 'f') || ('A' <= c
&& c
<= 'F');
377 static unsigned int _pp_identifier_end(const char *c
, unsigned int nr_c
, unsigned int start
)
383 if (pp_nondigit(c
[i
]) || pp_digit(c
[i
])) {
385 } else if (i
+ 5 < nr_c
&& c
[i
] == '\\' && c
[i
+ 1] == 'u' &&
386 pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) && pp_hexdigit(c
[i
+ 5])) {
388 } else if (i
+ 9 < nr_c
&& c
[i
] == '\\' && c
[i
+ 1] == 'U' &&
389 pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) && pp_hexdigit(c
[i
+ 5]) &&
390 pp_hexdigit(c
[i
+ 6]) && pp_hexdigit(c
[i
+ 7]) && pp_hexdigit(c
[i
+ 8]) && pp_hexdigit(c
[i
+ 9])) {
398 static unsigned int pp_number_end(const char *c
, unsigned int nr_c
, unsigned int start
)
404 if ((c
[i
] == 'e' || c
[i
] == 'E' || c
[i
] == 'p' || c
[i
] == 'P') &&
405 i
+ 1 < nr_c
&& (c
[i
+ 1] == '+' || c
[i
+ 1] == '-')) {
407 } else if (pp_digit(c
[i
]) || pp_nondigit(c
[i
]) || c
[i
] == '.') {
409 } else if (c
[i
] == '\\' && i
+ 5 < nr_c
&& c
[i
+ 1] == 'u' &&
410 pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) && pp_hexdigit(c
[i
+ 5])) {
412 } else if (c
[i
] == '\\' && i
+ 9 < nr_c
&& c
[i
+ 1] == 'U' &&
413 pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) && pp_hexdigit(c
[i
+ 5]) &&
414 pp_hexdigit(c
[i
+ 6]) && pp_hexdigit(c
[i
+ 7]) && pp_hexdigit(c
[i
+ 8]) && pp_hexdigit(c
[i
+ 9])) {
422 static unsigned int c_comment_end(const char *c
, unsigned int nr_c
, unsigned int start
)
427 while (i
+ 1 < nr_c
) {
428 if (c
[i
] == '*' && c
[i
+ 1] == '/')
435 static unsigned int cpp_comment_end(const char *c
, unsigned int nr_c
, unsigned int start
)
440 while (i
< nr_c
&& c
[i
] != '\n')
445 static unsigned int escape_sequence_end(const char *c
, unsigned int nr_c
, unsigned int start
, struct pos
*_pos
)
447 struct pos
*pos
= &_pos
[start
];
452 error_exit(pos
, "incomplete escape sequence");
454 case '\'':case '"':case '?':case '\\':
455 case 'a':case 'b':case 'f':case 'n':case 'r':case 't':case 'v':
457 case '0':case '1':case '2':case '3':case '4':case '6':case '7':
458 if (i
+ 2 < nr_c
&& pp_octdigit(c
[i
+ 1]) && pp_octdigit(c
[i
+ 2]))
460 if (i
+ 1 < nr_c
&& pp_octdigit(c
[i
+ 1]))
465 while (i
< nr_c
&& pp_hexdigit(c
[i
]))
468 error_exit(pos
, "invalid hexadecimal escape sequence");
472 pp_hexdigit(c
[i
+ 1]) && pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]))
474 error_exit(pos
, "invalid universal character name");
477 pp_hexdigit(c
[i
+ 1]) && pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) &&
478 pp_hexdigit(c
[i
+ 5]) && pp_hexdigit(c
[i
+ 6]) && pp_hexdigit(c
[i
+ 7]) && pp_hexdigit(c
[i
+ 8]))
480 error_exit(pos
, "invalid universal character name");
482 error_exit(pos
, "invalid escape sequence");
486 static unsigned int pp_string_end(const char *c
, unsigned int nr_c
, unsigned int start
, struct pos
*_pos
)
488 struct pos
*pos
= &_pos
[start
];
492 while (i
< nr_c
&& c
[i
] != '"') {
497 i
= escape_sequence_end(c
, nr_c
, i
, _pos
);
508 error_exit(pos
, "incomplete string literal");
511 static unsigned int pp_char_end(const char *c
, unsigned int nr_c
, unsigned int start
, struct pos
*_pos
)
513 struct pos
*pos
= &_pos
[start
];
517 while (i
< nr_c
&& c
[i
] != '\'') {
522 i
= escape_sequence_end(c
, nr_c
, i
, _pos
);
535 error_exit(pos
, "incomplete character constant");
537 error_exit(pos
, "empty character constant");
540 static unsigned int whitespace_end(const char *c
, unsigned int nr_c
, unsigned int start
)
545 while (i
< nr_c
&& (c
[i
] == ' ' || c
[i
] == '\t'))
550 static struct pp_token
*pp_define(const char *c
, unsigned int nr_c
, unsigned int *start
, struct pos
*pos
)
552 struct pp_token
*ppt
;
553 unsigned int name_start
, name_end
;
557 if (i
>= nr_c
|| !pp_nondigit(c
[i
]))
558 error_exit(pos
, "invalid #define directive");
560 i
= _pp_identifier_end(c
, nr_c
, i
+ 1);
563 ppt
= pp_token_create(PP_TOKEN_DEFINE
, pos
);
564 pp_token_add(ppt
, c
, name_start
, name_end
);
566 while (i
< nr_c
&& c
[i
] != '\n')
572 static struct pp_token
*pp_error(const char *c
, unsigned int nr_c
, unsigned int *start
, struct pos
*pos
)
577 while (j
< nr_c
&& c
[j
] != '\n')
579 error_exit(pos
, "%.*s", j
- *start
, &c
[*start
]);
582 static struct pp_token
*pp_include(const char *c
, unsigned int nr_c
, unsigned int *start
, struct pos
*pos
)
584 struct pp_token
*ppt
;
585 unsigned int name_start
, name_end
;
586 enum pp_token_type type
;
590 if (j
+ 2 >= nr_c
|| (c
[j
] != '<' && c
[j
] != '"'))
591 error_exit(pos
, "invalid #include directive");
594 if (c
[j
- 1] == '<') {
595 while (j
< nr_c
&& c
[j
] != '>')
597 type
= PP_TOKEN_INCLUDE_GLOBAL
;
599 while (j
< nr_c
&& c
[j
] != '"')
601 type
= PP_TOKEN_INCLUDE_LOCAL
;
604 error_exit(pos
, "invalid #include directive");
607 ppt
= pp_token_create(type
, pos
);
608 pp_token_add(ppt
, c
, name_start
, name_end
);
611 if (j
< nr_c
&& c
[j
] == '\n')
617 static struct pp_token
*pp_ifdef(const char *c
, unsigned int nr_c
, unsigned int *start
, struct pos
*pos
)
619 struct pp_token
*ppt
;
620 unsigned int name_start
, name_end
;
624 if (i
>= nr_c
|| !pp_nondigit(c
[i
]))
625 error_exit(pos
, "invalid #ifdef directive");
627 i
= _pp_identifier_end(c
, nr_c
, i
+ 1);
630 ppt
= pp_token_create(PP_TOKEN_IFDEF
, pos
);
631 pp_token_add(ppt
, c
, name_start
, name_end
);
633 while (i
< nr_c
&& c
[i
] != '\n')
639 static struct pp_token
*pp_ifndef(const char *c
, unsigned int nr_c
, unsigned int *start
, struct pos
*pos
)
641 struct pp_token
*ppt
;
642 unsigned int name_start
, name_end
;
646 if (i
>= nr_c
|| !pp_nondigit(c
[i
]))
647 error_exit(pos
, "invalid #ifndef directive");
649 i
= _pp_identifier_end(c
, nr_c
, i
+ 1);
652 ppt
= pp_token_create(PP_TOKEN_IFNDEF
, pos
);
653 pp_token_add(ppt
, c
, name_start
, name_end
);
655 while (i
< nr_c
&& c
[i
] != '\n')
661 static struct pp_token
*pp_tokenize(const char *c
, unsigned int nr_c
, struct pos
*_pos
)
663 struct pp_token
*ppt_head
, *ppt_tail
;
664 int pp_directive_allowed
;
668 pp_directive_allowed
= 1;
672 struct pp_token
*ppt
;
674 if (pp_directive_allowed
) {
675 static const struct __ppd
{
678 struct pp_token
* (*f
)(const char *c
, unsigned int nr_c
, unsigned int *start
, struct pos
*pos
);
680 { .len
= 6, .str
= "define", .f
= pp_define
, },
681 { .len
= 5, .str
= "error", .f
= pp_error
, },
682 { .len
= 7, .str
= "include", .f
= pp_include
, },
683 { .len
= 5, .str
= "ifdef", .f
= pp_ifdef
, },
684 { .len
= 6, .str
= "ifndef", .f
= pp_ifndef
, },
686 unsigned int sharp_start
, ppd_start
, ppd_end
;
689 j
= whitespace_end(c
, nr_c
, i
);
690 if (j
>= nr_c
|| c
[j
] != '#')
691 goto not_pp_directive
;
693 pos
= &_pos
[sharp_start
];
694 j
= whitespace_end(c
, nr_c
, j
+ 1);
696 warning(pos
, "empty preprocessor directive");
701 warning(pos
, "empty preprocessor directive");
702 /* Eat newline after # */
708 while (j
< nr_c
&& pp_nondigit(c
[j
]))
712 for (k
= 0; k
< sizeof(_ppd
) / sizeof(_ppd
[0]); k
++) {
713 const struct __ppd
*ppd
= &_ppd
[k
];
715 if (ppd_end
- ppd_start
== ppd
->len
&& memcmp(&c
[ppd_start
], ppd
->str
, ppd
->len
) == 0)
718 if (k
>= sizeof(_ppd
) / sizeof(_ppd
[0]))
719 error_exit(pos
, "unknown preprocessor directive '#%.*s'", ppd_end
- ppd_start
, &c
[ppd_start
]);
720 j
= whitespace_end(c
, nr_c
, j
);
721 ppt
= _ppd
[k
].f(c
, nr_c
, &j
, pos
);
733 ppt
= pp_token_create(' ', pos
);
737 ppt
= pp_token_create('\n', pos
);
749 ppt
= pp_token_create(c
[i
], pos
);
752 case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':
753 case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':
754 case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':
755 case 'v':case 'w':case 'x':case 'y':case 'z':
756 case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':
757 case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':
758 case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':
759 case 'V':case 'W':case 'X':case 'Y':case 'Z':
761 ppt
= pp_token_create(PP_TOKEN_IDENTIFIER
, pos
);
762 j
= _pp_identifier_end(c
, nr_c
, i
+ 1);
763 pp_token_add(ppt
, c
, i
, j
);
767 if (i
+ 5 < nr_c
&& c
[i
+ 1] == 'u' &&
768 pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) && pp_hexdigit(c
[i
+ 5])) {
769 ppt
= pp_token_create(PP_TOKEN_IDENTIFIER
, pos
);
770 j
= _pp_identifier_end(c
, nr_c
, i
+ 2 + 4);
771 pp_token_add(ppt
, c
, i
, j
);
773 } else if (i
+ 9 < nr_c
&& c
[i
+ 1] == 'U' &&
774 pp_hexdigit(c
[i
+ 2]) && pp_hexdigit(c
[i
+ 3]) && pp_hexdigit(c
[i
+ 4]) && pp_hexdigit(c
[i
+ 5]) &&
775 pp_hexdigit(c
[i
+ 6]) && pp_hexdigit(c
[i
+ 7]) && pp_hexdigit(c
[i
+ 8]) && pp_hexdigit(c
[i
+ 9])) {
776 ppt
= pp_token_create(PP_TOKEN_IDENTIFIER
, pos
);
777 j
= _pp_identifier_end(c
, nr_c
, i
+ 2 + 4 + 4);
778 pp_token_add(ppt
, c
, i
, j
);
781 error_exit(pos
, "unknown character %08"PRIx32
, c
[i
]);
783 case '0':case '1':case '2':case '3':case '4':
784 case '5':case '6':case '7':case '8':case '9':
785 ppt
= pp_token_create(PP_TOKEN_NUMBER
, pos
);
786 j
= pp_number_end(c
, nr_c
, i
);
787 pp_token_add(ppt
, c
, i
, j
);
791 if (i
+ 2 < nr_c
&& c
[i
+ 1] == '.' && c
[i
+ 2] == '.') {
792 ppt
= pp_token_create(PP_TOKEN_DOTDOTDOT
, pos
);
794 } else if (i
+ 1 < nr_c
&& pp_digit(c
[i
+ 1])) {
795 ppt
= pp_token_create(PP_TOKEN_NUMBER
, pos
);
796 j
= pp_number_end(c
, nr_c
, i
+ 1);
797 pp_token_add(ppt
, c
, i
, j
);
800 goto pp_token_simple
;
803 ppt
= pp_token_create(PP_TOKEN_STRING
, pos
);
804 j
= pp_string_end(c
, nr_c
, i
, _pos
);
805 pp_token_add(ppt
, c
, i
+ 1, j
- 1);
809 ppt
= pp_token_create(PP_TOKEN_CHAR
, pos
);
810 j
= pp_char_end(c
, nr_c
, i
, _pos
);
811 pp_token_add(ppt
, c
, i
+ 1, j
- 1);
815 if (i
+ 1 < nr_c
&& c
[i
+ 1] == '*') {
816 ppt
= pp_token_create(' ', pos
);
817 i
= c_comment_end(c
, nr_c
, i
);
818 } else if (i
+ 1 < nr_c
&& c
[i
+ 1] == '/') {
819 warning(pos
, "C++ comment");
820 ppt
= pp_token_create(' ', pos
);
821 i
= cpp_comment_end(c
, nr_c
, i
);
822 } else if (i
+ 1 < nr_c
&& c
[i
+ 1] == '=') {
823 ppt
= pp_token_create((c
[i
] << 8) | c
[i
+ 1], pos
);
826 goto pp_token_simple
;
829 if (i
+ 1 < nr_c
&& (c
[i
+ 1] == '>' || c
[i
+ 1] == '=' || c
[i
+ 1] == '-')) {
830 ppt
= pp_token_create((c
[i
] << 8) | c
[i
+ 1], pos
);
833 goto pp_token_simple
;
838 if (i
+ 1 < nr_c
&& (c
[i
+ 1] == '=' || c
[i
+ 1] == c
[i
])) {
839 ppt
= pp_token_create((c
[i
] << 8) | c
[i
+ 1], pos
);
842 goto pp_token_simple
;
849 if (i
+ 1 < nr_c
&& c
[i
+ 1] == '=') {
850 ppt
= pp_token_create((c
[i
] << 8) | c
[i
+ 1], pos
);
853 goto pp_token_simple
;
857 if (i
+ 2 < nr_c
&& c
[i
+ 1] == c
[i
] && c
[i
+ 2] == '=') {
858 ppt
= pp_token_create((c
[i
] << 16) | (c
[i
+ 1] << 8) | c
[i
+ 2], pos
);
860 } else if (i
+ 1 < nr_c
&& (c
[i
+ 1] == c
[i
] || c
[i
+ 1] == '=')) {
861 ppt
= pp_token_create((c
[i
] << 8) | c
[i
+ 1], pos
);
864 goto pp_token_simple
;
867 if (i
+ 1 < nr_c
&& c
[i
+ 1] == '#') {
868 ppt
= pp_token_create((c
[i
] << 8) | c
[i
+ 1], pos
);
871 goto pp_token_simple
;
874 error_exit(pos
, "unknown character %08"PRIx32
, c
[i
]);
877 if (ppt
->type
== '\n')
878 pp_directive_allowed
= 1;
879 else if (ppt
->type
== ' ')
882 pp_directive_allowed
= 0;
888 ppt_tail
->next
= ppt
;
894 int main(int argc
, char *argv
[])
898 unsigned int st_size
;
903 struct pp_token
*ppt_head
;
908 fd
= open(argv
[1], O_RDONLY
);
910 perror_exit("open %s", argv
[1]);
911 if (fstat(fd
, &st
) == -1)
912 perror_exit("fstat %s", argv
[1]);
914 _error_exit("%s: negative st_size %"PRIdMAX
, argv
[1], (intmax_t)st
.st_size
);
915 st_size
= (unsigned int)(uintmax_t)(intmax_t)st
.st_size
;
916 if ((uintmax_t)(intmax_t)st
.st_size
!= (uintmax_t)st_size
)
917 _error_exit("%s: too big st_size %"PRIdMAX
, argv
[1], (intmax_t)st
.st_size
);
919 buf
= xmalloc(st_size
);
920 xread(fd
, buf
, st_size
);
926 fix_newline(c
, &nr_c
);
927 pos
= line_column(c
, nr_c
);
928 warn_trigraph(c
, nr_c
, pos
);
929 delete_backslash_newline(c
, &nr_c
, pos
);
931 ppt_head
= pp_tokenize(c
, nr_c
, pos
);
936 struct pp_token
*ppt
;
938 for (ppt
= ppt_head
; ppt
; ppt
= ppt
->next
) {
943 pp_token_free(ppt_head
);