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