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