(root)/
libpng-1.6.40/
contrib/
arm-neon/
linux.c
       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  }