1 | /* contrib/arm-neon/linux.c
|
---|
2 | *
|
---|
3 | * Copyright (c) 2014, 2017 Glenn Randers-Pehrson
|
---|
4 | * Written by John Bowler, 2014, 2017.
|
---|
5 | *
|
---|
6 | * This code is released under the libpng license.
|
---|
7 | * For conditions of distribution and use, see the disclaimer
|
---|
8 | * and license in png.h
|
---|
9 | *
|
---|
10 | * SEE contrib/arm-neon/README before reporting bugs
|
---|
11 | *
|
---|
12 | * STATUS: SUPPORTED
|
---|
13 | * BUG REPORTS: png-mng-implement@sourceforge.net
|
---|
14 | *
|
---|
15 | * png_have_neon implemented for Linux by reading the widely available
|
---|
16 | * pseudo-file /proc/cpuinfo.
|
---|
17 | *
|
---|
18 | * This code is strict ANSI-C and is probably moderately portable; it does
|
---|
19 | * however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
|
---|
20 | */
|
---|
21 |
|
---|
22 | #include <stdio.h>
|
---|
23 |
|
---|
24 | static int
|
---|
25 | png_have_neon(png_structp png_ptr)
|
---|
26 | {
|
---|
27 | FILE *f = fopen("/proc/cpuinfo", "rb");
|
---|
28 |
|
---|
29 | if (f != NULL)
|
---|
30 | {
|
---|
31 | /* This is a simple state machine which reads the input byte-by-byte until
|
---|
32 | * it gets a match on the 'neon' feature or reaches the end of the stream.
|
---|
33 | */
|
---|
34 | static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 };
|
---|
35 | static const char ch_neon[] = { 78, 69, 79, 78 };
|
---|
36 |
|
---|
37 | enum
|
---|
38 | {
|
---|
39 | StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine
|
---|
40 | } state;
|
---|
41 | int counter;
|
---|
42 |
|
---|
43 | for (state=StartLine, counter=0;;)
|
---|
44 | {
|
---|
45 | int ch = fgetc(f);
|
---|
46 |
|
---|
47 | if (ch == EOF)
|
---|
48 | {
|
---|
49 | /* EOF means error or end-of-file, return false; neon at EOF is
|
---|
50 | * assumed to be a mistake.
|
---|
51 | */
|
---|
52 | fclose(f);
|
---|
53 | return 0;
|
---|
54 | }
|
---|
55 |
|
---|
56 | switch (state)
|
---|
57 | {
|
---|
58 | case StartLine:
|
---|
59 | /* Match spaces at the start of line */
|
---|
60 | if (ch <= 32) /* skip control characters and space */
|
---|
61 | break;
|
---|
62 |
|
---|
63 | counter=0;
|
---|
64 | state = Feature;
|
---|
65 | /* FALLTHROUGH */
|
---|
66 |
|
---|
67 | case Feature:
|
---|
68 | /* Match 'FEATURE', ASCII case insensitive. */
|
---|
69 | if ((ch & ~0x20) == ch_feature[counter])
|
---|
70 | {
|
---|
71 | if (++counter == (sizeof ch_feature))
|
---|
72 | state = Colon;
|
---|
73 | break;
|
---|
74 | }
|
---|
75 |
|
---|
76 | /* did not match 'feature' */
|
---|
77 | state = SkipLine;
|
---|
78 | /* FALLTHROUGH */
|
---|
79 |
|
---|
80 | case SkipLine:
|
---|
81 | skipLine:
|
---|
82 | /* Skip everything until we see linefeed or carriage return */
|
---|
83 | if (ch != 10 && ch != 13)
|
---|
84 | break;
|
---|
85 |
|
---|
86 | state = StartLine;
|
---|
87 | break;
|
---|
88 |
|
---|
89 | case Colon:
|
---|
90 | /* Match any number of space or tab followed by ':' */
|
---|
91 | if (ch == 32 || ch == 9)
|
---|
92 | break;
|
---|
93 |
|
---|
94 | if (ch == 58) /* i.e. ':' */
|
---|
95 | {
|
---|
96 | state = StartTag;
|
---|
97 | break;
|
---|
98 | }
|
---|
99 |
|
---|
100 | /* Either a bad line format or a 'feature' prefix followed by
|
---|
101 | * other characters.
|
---|
102 | */
|
---|
103 | state = SkipLine;
|
---|
104 | goto skipLine;
|
---|
105 |
|
---|
106 | case StartTag:
|
---|
107 | /* Skip space characters before a tag */
|
---|
108 | if (ch == 32 || ch == 9)
|
---|
109 | break;
|
---|
110 |
|
---|
111 | state = Neon;
|
---|
112 | counter = 0;
|
---|
113 | /* FALLTHROUGH */
|
---|
114 |
|
---|
115 | case Neon:
|
---|
116 | /* Look for 'neon' tag */
|
---|
117 | if ((ch & ~0x20) == ch_neon[counter])
|
---|
118 | {
|
---|
119 | if (++counter == (sizeof ch_neon))
|
---|
120 | state = HaveNeon;
|
---|
121 | break;
|
---|
122 | }
|
---|
123 |
|
---|
124 | state = SkipTag;
|
---|
125 | /* FALLTHROUGH */
|
---|
126 |
|
---|
127 | case SkipTag:
|
---|
128 | /* Skip non-space characters */
|
---|
129 | if (ch == 10 || ch == 13)
|
---|
130 | state = StartLine;
|
---|
131 |
|
---|
132 | else if (ch == 32 || ch == 9)
|
---|
133 | state = StartTag;
|
---|
134 | break;
|
---|
135 |
|
---|
136 | case HaveNeon:
|
---|
137 | /* Have seen a 'neon' prefix, but there must be a space or new
|
---|
138 | * line character to terminate it.
|
---|
139 | */
|
---|
140 | if (ch == 10 || ch == 13 || ch == 32 || ch == 9)
|
---|
141 | {
|
---|
142 | fclose(f);
|
---|
143 | return 1;
|
---|
144 | }
|
---|
145 |
|
---|
146 | state = SkipTag;
|
---|
147 | break;
|
---|
148 |
|
---|
149 | default:
|
---|
150 | png_error(png_ptr, "png_have_neon: internal error (bug)");
|
---|
151 | }
|
---|
152 | }
|
---|
153 | }
|
---|
154 |
|
---|
155 | #ifdef PNG_WARNINGS_SUPPORTED
|
---|
156 | else
|
---|
157 | png_warning(png_ptr, "/proc/cpuinfo open failed");
|
---|
158 | #endif
|
---|
159 |
|
---|
160 | return 0;
|
---|
161 | }
|
---|